fxn 0.0.39__tar.gz → 0.0.41__tar.gz
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.
- {fxn-0.0.39 → fxn-0.0.41}/PKG-INFO +7 -7
- {fxn-0.0.39 → fxn-0.0.41}/README.md +6 -6
- fxn-0.0.41/fxn/c/__init__.py +13 -0
- fxn-0.0.41/fxn/c/configuration.py +118 -0
- fxn-0.0.41/fxn/c/fxnc.py +48 -0
- fxn-0.0.41/fxn/c/map.py +64 -0
- fxn-0.0.41/fxn/c/prediction.py +76 -0
- fxn-0.0.41/fxn/c/predictor.py +60 -0
- fxn-0.0.41/fxn/c/stream.py +41 -0
- fxn-0.0.41/fxn/c/value.py +223 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/cli/__init__.py +6 -2
- fxn-0.0.39/fxn/cli/predict.py → fxn-0.0.41/fxn/cli/predictions.py +32 -35
- fxn-0.0.41/fxn/client.py +46 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/function.py +4 -4
- fxn-0.0.41/fxn/lib/linux/arm64/libFunction.so +0 -0
- fxn-0.0.41/fxn/lib/linux/x86_64/libFunction.so +0 -0
- fxn-0.0.41/fxn/lib/macos/arm64/Function.dylib +0 -0
- fxn-0.0.41/fxn/lib/macos/x86_64/Function.dylib +0 -0
- fxn-0.0.41/fxn/lib/windows/arm64/Function.dll +0 -0
- fxn-0.0.41/fxn/lib/windows/x86_64/Function.dll +0 -0
- fxn-0.0.41/fxn/services/__init__.py +8 -0
- fxn-0.0.41/fxn/services/prediction.py +278 -0
- fxn-0.0.41/fxn/services/predictor.py +30 -0
- fxn-0.0.41/fxn/services/user.py +27 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/types/__init__.py +1 -1
- {fxn-0.0.39 → fxn-0.0.41}/fxn/types/prediction.py +8 -8
- {fxn-0.0.39 → fxn-0.0.41}/fxn/types/predictor.py +18 -21
- fxn-0.0.41/fxn/types/user.py +29 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/version.py +1 -1
- {fxn-0.0.39 → fxn-0.0.41}/fxn.egg-info/PKG-INFO +7 -7
- {fxn-0.0.39 → fxn-0.0.41}/fxn.egg-info/SOURCES.txt +2 -6
- fxn-0.0.39/fxn/api/__init__.py +0 -6
- fxn-0.0.39/fxn/api/client.py +0 -43
- fxn-0.0.39/fxn/c/__init__.py +0 -16
- fxn-0.0.39/fxn/c/configuration.py +0 -60
- fxn-0.0.39/fxn/c/dtype.py +0 -26
- fxn-0.0.39/fxn/c/fxnc.py +0 -28
- fxn-0.0.39/fxn/c/map.py +0 -34
- fxn-0.0.39/fxn/c/prediction.py +0 -37
- fxn-0.0.39/fxn/c/predictor.py +0 -31
- fxn-0.0.39/fxn/c/status.py +0 -12
- fxn-0.0.39/fxn/c/stream.py +0 -22
- fxn-0.0.39/fxn/c/value.py +0 -50
- fxn-0.0.39/fxn/c/version.py +0 -13
- fxn-0.0.39/fxn/lib/linux/arm64/libFunction.so +0 -0
- fxn-0.0.39/fxn/lib/linux/x86_64/libFunction.so +0 -0
- fxn-0.0.39/fxn/lib/macos/arm64/Function.dylib +0 -0
- fxn-0.0.39/fxn/lib/macos/x86_64/Function.dylib +0 -0
- fxn-0.0.39/fxn/lib/windows/arm64/Function.dll +0 -0
- fxn-0.0.39/fxn/lib/windows/x86_64/Function.dll +0 -0
- fxn-0.0.39/fxn/services/__init__.py +0 -8
- fxn-0.0.39/fxn/services/prediction.py +0 -450
- fxn-0.0.39/fxn/services/predictor.py +0 -206
- fxn-0.0.39/fxn/services/user.py +0 -56
- fxn-0.0.39/fxn/types/user.py +0 -35
- {fxn-0.0.39 → fxn-0.0.41}/LICENSE +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/__init__.py +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/cli/auth.py +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/cli/env.py +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/cli/misc.py +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/cli/predictors.py +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/lib/__init__.py +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn/types/dtype.py +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn.egg-info/dependency_links.txt +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn.egg-info/entry_points.txt +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn.egg-info/requires.txt +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/fxn.egg-info/top_level.txt +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/pyproject.toml +0 -0
- {fxn-0.0.39 → fxn-0.0.41}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fxn
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.41
|
4
4
|
Summary: Run prediction functions locally in Python. Register at https://fxn.ai.
|
5
5
|
Author-email: "NatML Inc." <hi@fxn.ai>
|
6
6
|
License: Apache License
|
@@ -227,9 +227,12 @@ Requires-Dist: typer
|
|
227
227
|
|
228
228
|

|
229
229
|
|
230
|
-
[](https://
|
230
|
+
[](https://discord.gg/fxn)
|
231
231
|
|
232
|
-
Run prediction functions (a.k.a "predictors") locally in your Python apps, with full GPU acceleration and zero dependencies.
|
232
|
+
Run prediction functions (a.k.a "predictors") locally in your Python apps, with full GPU acceleration and zero dependencies.
|
233
|
+
|
234
|
+
> [!TIP]
|
235
|
+
> [Join our waitlist](https://fxn.ai/waitlist) to bring your custom Python functions and run them on-device across Android, iOS, macOS, Linux, web, and Windows.
|
233
236
|
|
234
237
|
## Installing Function
|
235
238
|
Function is distributed on PyPi. This distribution contains both the Python client and the command line interface (CLI). To install, open a terminal and run the following command:
|
@@ -266,9 +269,6 @@ prediction = fxn.predictions.create(
|
|
266
269
|
print(prediction.results[0])
|
267
270
|
```
|
268
271
|
|
269
|
-
> [!TIP]
|
270
|
-
> Explore public predictors [on Function](https://fxn.ai/explore) or [create your own](https://fxn.ai/waitlist).
|
271
|
-
|
272
272
|
## Using the Function CLI
|
273
273
|
Open up a terminal and login to the Function CLI:
|
274
274
|
```sh
|
@@ -286,7 +286,7 @@ ___
|
|
286
286
|
|
287
287
|
## Useful Links
|
288
288
|
- [Discover predictors to use in your apps](https://fxn.ai/explore).
|
289
|
-
- [Join our Discord community](https://
|
289
|
+
- [Join our Discord community](https://discord.gg/fxn).
|
290
290
|
- [Check out our docs](https://docs.fxn.ai).
|
291
291
|
- Learn more about us [on our blog](https://blog.fxn.ai).
|
292
292
|
- Reach out to us at [hi@fxn.ai](mailto:hi@fxn.ai).
|
@@ -2,9 +2,12 @@
|
|
2
2
|
|
3
3
|

|
4
4
|
|
5
|
-
[](https://
|
5
|
+
[](https://discord.gg/fxn)
|
6
6
|
|
7
|
-
Run prediction functions (a.k.a "predictors") locally in your Python apps, with full GPU acceleration and zero dependencies.
|
7
|
+
Run prediction functions (a.k.a "predictors") locally in your Python apps, with full GPU acceleration and zero dependencies.
|
8
|
+
|
9
|
+
> [!TIP]
|
10
|
+
> [Join our waitlist](https://fxn.ai/waitlist) to bring your custom Python functions and run them on-device across Android, iOS, macOS, Linux, web, and Windows.
|
8
11
|
|
9
12
|
## Installing Function
|
10
13
|
Function is distributed on PyPi. This distribution contains both the Python client and the command line interface (CLI). To install, open a terminal and run the following command:
|
@@ -41,9 +44,6 @@ prediction = fxn.predictions.create(
|
|
41
44
|
print(prediction.results[0])
|
42
45
|
```
|
43
46
|
|
44
|
-
> [!TIP]
|
45
|
-
> Explore public predictors [on Function](https://fxn.ai/explore) or [create your own](https://fxn.ai/waitlist).
|
46
|
-
|
47
47
|
## Using the Function CLI
|
48
48
|
Open up a terminal and login to the Function CLI:
|
49
49
|
```sh
|
@@ -61,7 +61,7 @@ ___
|
|
61
61
|
|
62
62
|
## Useful Links
|
63
63
|
- [Discover predictors to use in your apps](https://fxn.ai/explore).
|
64
|
-
- [Join our Discord community](https://
|
64
|
+
- [Join our Discord community](https://discord.gg/fxn).
|
65
65
|
- [Check out our docs](https://docs.fxn.ai).
|
66
66
|
- Learn more about us [on our blog](https://blog.fxn.ai).
|
67
67
|
- Reach out to us at [hi@fxn.ai](mailto:hi@fxn.ai).
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#
|
2
|
+
# Function
|
3
|
+
# Copyright © 2024 NatML Inc. All Rights Reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
# https://github.com/fxnai/fxnc
|
7
|
+
|
8
|
+
from .configuration import Configuration
|
9
|
+
from .map import ValueMap
|
10
|
+
from .prediction import Prediction
|
11
|
+
from .predictor import Predictor
|
12
|
+
from .stream import PredictionStream
|
13
|
+
from .value import Value, ValueFlags
|
@@ -0,0 +1,118 @@
|
|
1
|
+
#
|
2
|
+
# Function
|
3
|
+
# Copyright © 2024 NatML Inc. All Rights Reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
from ctypes import byref, c_int, c_void_p, create_string_buffer
|
7
|
+
from pathlib import Path
|
8
|
+
from typing import final
|
9
|
+
|
10
|
+
from ..types import Acceleration
|
11
|
+
from .fxnc import get_fxnc, status_to_error, FXNStatus
|
12
|
+
|
13
|
+
@final
|
14
|
+
class Configuration:
|
15
|
+
|
16
|
+
def __init__ (self):
|
17
|
+
configuration = c_void_p()
|
18
|
+
status = get_fxnc().FXNConfigurationCreate(byref(configuration))
|
19
|
+
if status == FXNStatus.OK:
|
20
|
+
self.__configuration = configuration
|
21
|
+
else:
|
22
|
+
raise RuntimeError(f"Failed to create configuration with error: {status_to_error(status)}")
|
23
|
+
|
24
|
+
@property
|
25
|
+
def tag (self) -> str:
|
26
|
+
buffer = create_string_buffer(2048)
|
27
|
+
status = get_fxnc().FXNConfigurationGetTag(self.__configuration, buffer, len(buffer))
|
28
|
+
if status != FXNStatus.OK:
|
29
|
+
raise RuntimeError(f"Failed to get configuration tag with error: {status_to_error(status)}")
|
30
|
+
tag = buffer.value.decode("utf-8")
|
31
|
+
return tag if tag else None
|
32
|
+
|
33
|
+
@tag.setter
|
34
|
+
def tag (self, tag: str):
|
35
|
+
tag = tag.encode() if tag is not None else None
|
36
|
+
status = get_fxnc().FXNConfigurationSetTag(self.__configuration, tag)
|
37
|
+
if status != FXNStatus.OK:
|
38
|
+
raise RuntimeError(f"Failed to set configuration tag with error: {status_to_error(status)}")
|
39
|
+
|
40
|
+
@property
|
41
|
+
def token (self) -> str:
|
42
|
+
buffer = create_string_buffer(2048)
|
43
|
+
status = get_fxnc().FXNConfigurationGetToken(self.__configuration, buffer, len(buffer))
|
44
|
+
if status != FXNStatus.OK:
|
45
|
+
raise RuntimeError(f"Failed to get configuration token with error: {status_to_error(status)}")
|
46
|
+
token = buffer.value.decode("utf-8")
|
47
|
+
return token if token else None
|
48
|
+
|
49
|
+
@token.setter
|
50
|
+
def token (self, token: str):
|
51
|
+
token = token.encode() if token is not None else None
|
52
|
+
status = get_fxnc().FXNConfigurationSetToken(self.__configuration, token)
|
53
|
+
if status != FXNStatus.OK:
|
54
|
+
raise RuntimeError(f"Failed to set configuration token with error: {status_to_error(status)}")
|
55
|
+
|
56
|
+
@property
|
57
|
+
def acceleration (self) -> Acceleration:
|
58
|
+
acceleration = c_int()
|
59
|
+
status = get_fxnc().FXNConfigurationGetAcceleration(self.__configuration, byref(acceleration))
|
60
|
+
if status == FXNStatus.OK:
|
61
|
+
return Acceleration(acceleration.value)
|
62
|
+
else:
|
63
|
+
raise RuntimeError(f"Failed to get configuration acceleration with error: {status_to_error(status)}")
|
64
|
+
|
65
|
+
@acceleration.setter
|
66
|
+
def acceleration (self, acceleration: Acceleration):
|
67
|
+
status = get_fxnc().FXNConfigurationSetAcceleration(self.__configuration, acceleration.value)
|
68
|
+
if status != FXNStatus.OK:
|
69
|
+
raise RuntimeError(f"Failed to set configuration acceleration with error: {status_to_error(status)}")
|
70
|
+
|
71
|
+
@property
|
72
|
+
def device (self):
|
73
|
+
device = c_void_p()
|
74
|
+
status = get_fxnc().FXNConfigurationGetDevice(self.__configuration, byref(device))
|
75
|
+
if status == FXNStatus.OK:
|
76
|
+
return device if device.value else None
|
77
|
+
else:
|
78
|
+
raise RuntimeError(f"Failed to get configuration device with error: {status_to_error(status)}")
|
79
|
+
|
80
|
+
@device.setter
|
81
|
+
def device (self, device):
|
82
|
+
status = get_fxnc().FXNConfigurationSetDevice(self.__configuration, device)
|
83
|
+
if status != FXNStatus.OK:
|
84
|
+
raise RuntimeError(f"Failed to set configuration device with error: {status_to_error(status)}")
|
85
|
+
|
86
|
+
def add_resource (self, type: str, path: Path):
|
87
|
+
status = get_fxnc().FXNConfigurationAddResource(self.__configuration, type.encode(), str(path).encode())
|
88
|
+
if status != FXNStatus.OK:
|
89
|
+
raise RuntimeError(f"Failed to add configuration resource with error: {status_to_error(status)}")
|
90
|
+
|
91
|
+
def __enter__ (self):
|
92
|
+
return self
|
93
|
+
|
94
|
+
def __exit__ (self, exc_type, exc_value, traceback):
|
95
|
+
self.__release()
|
96
|
+
|
97
|
+
def __release (self):
|
98
|
+
if self.__configuration:
|
99
|
+
get_fxnc().FXNConfigurationRelease(self.__configuration)
|
100
|
+
self.__configuration = None
|
101
|
+
|
102
|
+
@classmethod
|
103
|
+
def get_unique_id (cls) -> str:
|
104
|
+
buffer = create_string_buffer(2048)
|
105
|
+
status = get_fxnc().FXNConfigurationGetUniqueID(buffer, len(buffer))
|
106
|
+
if status == FXNStatus.OK:
|
107
|
+
return buffer.value.decode("utf-8")
|
108
|
+
else:
|
109
|
+
raise RuntimeError(f"Failed to retrieve configuration identifier with error: {status_to_error(status)}")
|
110
|
+
|
111
|
+
@classmethod
|
112
|
+
def get_client_id (cls) -> str:
|
113
|
+
buffer = create_string_buffer(64)
|
114
|
+
status = get_fxnc().FXNConfigurationGetClientID(buffer, len(buffer))
|
115
|
+
if status == FXNStatus.OK:
|
116
|
+
return buffer.value.decode("utf-8")
|
117
|
+
else:
|
118
|
+
raise RuntimeError(f"Failed to retrieve client identifier with error: {status_to_error(status)}")
|
fxn-0.0.41/fxn/c/fxnc.py
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#
|
2
|
+
# Function
|
3
|
+
# Copyright © 2024 NatML Inc. All Rights Reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
from ctypes import CDLL
|
7
|
+
from enum import IntEnum
|
8
|
+
from importlib import resources
|
9
|
+
from platform import machine, system
|
10
|
+
|
11
|
+
_fxnc: CDLL = None
|
12
|
+
|
13
|
+
class FXNStatus(IntEnum):
|
14
|
+
OK = 0
|
15
|
+
ERROR_INVALID_ARGUMENT = 1
|
16
|
+
ERROR_INVALID_OPERATION = 2
|
17
|
+
ERROR_NOT_IMPLEMENTED = 3
|
18
|
+
|
19
|
+
def get_fxnc () -> CDLL:
|
20
|
+
global _fxnc
|
21
|
+
_fxnc = _fxnc if _fxnc is not None else _load_fxnc()
|
22
|
+
return _fxnc
|
23
|
+
|
24
|
+
def set_fxnc (fxnc: CDLL):
|
25
|
+
global _fxnc
|
26
|
+
_fxnc = fxnc
|
27
|
+
|
28
|
+
def _load_fxnc () -> CDLL:
|
29
|
+
os = system().lower()
|
30
|
+
os = "macos" if os == "darwin" else os
|
31
|
+
arch = machine().lower()
|
32
|
+
arch = "arm64" if arch == "aarch64" else arch
|
33
|
+
arch = "x86_64" if arch in ["x64", "amd64"] else arch
|
34
|
+
package = f"fxn.lib.{os}.{arch}"
|
35
|
+
resource = "libFunction.so"
|
36
|
+
resource = "Function.dylib" if os == "macos" else resource
|
37
|
+
resource = "Function.dll" if os == "windows" else resource
|
38
|
+
with resources.path(package, resource) as path:
|
39
|
+
return CDLL(str(path))
|
40
|
+
|
41
|
+
def status_to_error (status: int) -> str:
|
42
|
+
if status == FXNStatus.ERROR_INVALID_ARGUMENT:
|
43
|
+
return "FXN_ERROR_INVALID_ARGUMENT"
|
44
|
+
elif status == FXNStatus.ERROR_INVALID_OPERATION:
|
45
|
+
return "FXN_ERROR_INVALID_OPERATION"
|
46
|
+
elif status == FXNStatus.ERROR_NOT_IMPLEMENTED:
|
47
|
+
return "FXN_ERROR_NOT_IMPLEMENTED"
|
48
|
+
return ""
|
fxn-0.0.41/fxn/c/map.py
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#
|
2
|
+
# Function
|
3
|
+
# Copyright © 2024 NatML Inc. All Rights Reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
from ctypes import byref, c_int, c_int32, c_void_p, create_string_buffer
|
7
|
+
from pathlib import Path
|
8
|
+
from typing import final
|
9
|
+
|
10
|
+
from .fxnc import get_fxnc, status_to_error, FXNStatus
|
11
|
+
from .value import Value
|
12
|
+
|
13
|
+
@final
|
14
|
+
class ValueMap:
|
15
|
+
|
16
|
+
def __init__ (self, map=None, *, owner: bool=True):
|
17
|
+
if map is None:
|
18
|
+
map = c_void_p()
|
19
|
+
owner = True
|
20
|
+
status = get_fxnc().FXNValueMapCreate(byref(map))
|
21
|
+
if status != FXNStatus.OK:
|
22
|
+
raise RuntimeError(f"Failed to create value map with error: {status_to_error(status)}")
|
23
|
+
self.__map = map
|
24
|
+
self.__owner = owner
|
25
|
+
|
26
|
+
def key (self, index: int) -> str:
|
27
|
+
buffer = create_string_buffer(256)
|
28
|
+
status = get_fxnc().FXNValueMapGetKey(self.__map, index, buffer, len(buffer))
|
29
|
+
if status == FXNStatus.OK:
|
30
|
+
return buffer.value.decode("utf-8")
|
31
|
+
else:
|
32
|
+
raise RuntimeError(f"Failed to get value map key at index {index} with error: {status_to_error(status)}")
|
33
|
+
|
34
|
+
def __getitem__ (self, key: str) -> Value | None:
|
35
|
+
value = c_void_p()
|
36
|
+
status = get_fxnc().FXNValueMapGetValue(self.__map, key.encode(), byref(value))
|
37
|
+
if status == FXNStatus.OK:
|
38
|
+
return Value(value, owner=False)
|
39
|
+
else:
|
40
|
+
raise RuntimeError(f"Failed to get value map value for key '{key}' with error: {status_to_error(status)}")
|
41
|
+
|
42
|
+
def __setitem__ (self, key: str, value: Value):
|
43
|
+
status = get_fxnc().FXNValueMapSetValue(self.__map, key.encode(), value._Value__value)
|
44
|
+
if status != FXNStatus.OK:
|
45
|
+
raise RuntimeError(f"Failed to set value map value for key '{key}' with error: {status_to_error(status)}")
|
46
|
+
|
47
|
+
def __len__ (self) -> int:
|
48
|
+
count = c_int32()
|
49
|
+
status = get_fxnc().FXNValueMapGetSize(self.__map, byref(count))
|
50
|
+
if status == FXNStatus.OK:
|
51
|
+
return count.value
|
52
|
+
else:
|
53
|
+
raise RuntimeError(f"Failed to get value map size with error: {status_to_error(status)}")
|
54
|
+
|
55
|
+
def __enter__ (self):
|
56
|
+
return self
|
57
|
+
|
58
|
+
def __exit__ (self, exc_type, exc_value, traceback):
|
59
|
+
self.__release()
|
60
|
+
|
61
|
+
def __release (self):
|
62
|
+
if self.__map and self.__owner:
|
63
|
+
get_fxnc().FXNValueMapRelease(self.__map)
|
64
|
+
self.__map = None
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#
|
2
|
+
# Function
|
3
|
+
# Copyright © 2024 NatML Inc. All Rights Reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
from ctypes import byref, c_double, c_int, c_int32, c_void_p, create_string_buffer
|
7
|
+
from pathlib import Path
|
8
|
+
from typing import final
|
9
|
+
|
10
|
+
from .fxnc import get_fxnc, status_to_error, FXNStatus
|
11
|
+
from .map import ValueMap
|
12
|
+
|
13
|
+
@final
|
14
|
+
class Prediction:
|
15
|
+
|
16
|
+
def __init__ (self, prediction):
|
17
|
+
self.__prediction = prediction
|
18
|
+
|
19
|
+
@property
|
20
|
+
def id (self) -> str:
|
21
|
+
id = create_string_buffer(256)
|
22
|
+
status = get_fxnc().FXNPredictionGetID(self.__prediction, id, len(id))
|
23
|
+
if status == FXNStatus.OK:
|
24
|
+
return id.value.decode("utf-8")
|
25
|
+
else:
|
26
|
+
raise RuntimeError(f"Failed to get prediction id with error: {status_to_error(status)}")
|
27
|
+
|
28
|
+
@property
|
29
|
+
def latency (self) -> float:
|
30
|
+
latency = c_double()
|
31
|
+
status = get_fxnc().FXNPredictionGetLatency(self.__prediction, byref(latency))
|
32
|
+
if status == FXNStatus.OK:
|
33
|
+
return latency.value
|
34
|
+
else:
|
35
|
+
raise RuntimeError(f"Failed to get prediction latency with error: {status_to_error(status)}")
|
36
|
+
|
37
|
+
@property
|
38
|
+
def results (self) -> ValueMap | None:
|
39
|
+
map = c_void_p()
|
40
|
+
status = get_fxnc().FXNPredictionGetResults(self.__prediction, byref(map))
|
41
|
+
if status != FXNStatus.OK:
|
42
|
+
raise RuntimeError(f"Failed to get prediction results with error: {status_to_error(status)}")
|
43
|
+
map = ValueMap(map, owner=False)
|
44
|
+
return map if len(map) > 0 else None
|
45
|
+
|
46
|
+
@property
|
47
|
+
def error (self) -> str | None:
|
48
|
+
error = create_string_buffer(2048)
|
49
|
+
get_fxnc().FXNPredictionGetError(self.__prediction, error, len(error))
|
50
|
+
error = error.value.decode("utf-8")
|
51
|
+
return error if error else None
|
52
|
+
|
53
|
+
@property
|
54
|
+
def logs (self) -> str:
|
55
|
+
fxnc = get_fxnc()
|
56
|
+
log_length = c_int32()
|
57
|
+
status = fxnc.FXNPredictionGetLogLength(self.__prediction, byref(log_length))
|
58
|
+
if status != FXNStatus.OK:
|
59
|
+
raise RuntimeError(f"Failed to get prediction log length with error: {status_to_error(status)}")
|
60
|
+
logs = create_string_buffer(log_length.value + 1)
|
61
|
+
status = fxnc.FXNPredictionGetLogs(self.__prediction, logs, len(logs))
|
62
|
+
if status == FXNStatus.OK:
|
63
|
+
return logs.value.decode("utf-8")
|
64
|
+
else:
|
65
|
+
raise RuntimeError(f"Failed to get prediction logs with error: {status_to_error(status)}")
|
66
|
+
|
67
|
+
def __enter__ (self):
|
68
|
+
return self
|
69
|
+
|
70
|
+
def __exit__ (self, exc_type, exc_value, traceback):
|
71
|
+
self.__release()
|
72
|
+
|
73
|
+
def __release (self):
|
74
|
+
if self.__prediction:
|
75
|
+
get_fxnc().FXNPredictionRelease(self.__prediction)
|
76
|
+
self.__prediction = None
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#
|
2
|
+
# Function
|
3
|
+
# Copyright © 2024 NatML Inc. All Rights Reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
from ctypes import byref, c_int, c_int32, c_void_p, create_string_buffer
|
7
|
+
from pathlib import Path
|
8
|
+
from typing import final
|
9
|
+
|
10
|
+
from .configuration import Configuration
|
11
|
+
from .fxnc import get_fxnc, status_to_error, FXNStatus
|
12
|
+
from .map import ValueMap
|
13
|
+
from .prediction import Prediction
|
14
|
+
from .stream import PredictionStream
|
15
|
+
|
16
|
+
@final
|
17
|
+
class Predictor:
|
18
|
+
|
19
|
+
def __init__ (self, configuration: Configuration):
|
20
|
+
predictor = c_void_p()
|
21
|
+
status = get_fxnc().FXNPredictorCreate(configuration._Configuration__configuration, byref(predictor))
|
22
|
+
if status == FXNStatus.OK:
|
23
|
+
self.__predictor = predictor
|
24
|
+
else:
|
25
|
+
raise RuntimeError(f"Failed to create predictor with error: {status_to_error(status)}")
|
26
|
+
|
27
|
+
def create_prediction (self, inputs: ValueMap) -> Prediction:
|
28
|
+
prediction = c_void_p()
|
29
|
+
status = get_fxnc().FXNPredictorCreatePrediction(
|
30
|
+
self.__predictor,
|
31
|
+
inputs._ValueMap__map,
|
32
|
+
byref(prediction)
|
33
|
+
)
|
34
|
+
if status == FXNStatus.OK:
|
35
|
+
return Prediction(prediction)
|
36
|
+
else:
|
37
|
+
raise RuntimeError(f"Failed to create prediction with error: {status_to_error(status)}")
|
38
|
+
|
39
|
+
def stream_prediction (self, inputs: ValueMap) -> PredictionStream:
|
40
|
+
stream = c_void_p()
|
41
|
+
status = get_fxnc().FXNPredictorStreamPrediction(
|
42
|
+
self.__predictor,
|
43
|
+
inputs._ValueMap__map,
|
44
|
+
byref(stream)
|
45
|
+
)
|
46
|
+
if status == FXNStatus.OK:
|
47
|
+
return PredictionStream(stream)
|
48
|
+
else:
|
49
|
+
raise RuntimeError(f"Failed to stream prediction with error: {status_to_error(status)}")
|
50
|
+
|
51
|
+
def __enter__ (self):
|
52
|
+
return self
|
53
|
+
|
54
|
+
def __exit__ (self, exc_type, exc_value, traceback):
|
55
|
+
self.__release()
|
56
|
+
|
57
|
+
def __release (self):
|
58
|
+
if self.__predictor:
|
59
|
+
get_fxnc().FXNPredictorRelease(self.__predictor)
|
60
|
+
self.__predictor = None
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#
|
2
|
+
# Function
|
3
|
+
# Copyright © 2024 NatML Inc. All Rights Reserved.
|
4
|
+
#
|
5
|
+
|
6
|
+
from ctypes import byref, c_int, c_int32, c_void_p, create_string_buffer
|
7
|
+
from pathlib import Path
|
8
|
+
from typing import final
|
9
|
+
|
10
|
+
from .fxnc import get_fxnc, status_to_error, FXNStatus
|
11
|
+
from .prediction import Prediction
|
12
|
+
|
13
|
+
@final
|
14
|
+
class PredictionStream:
|
15
|
+
|
16
|
+
def __init__ (self, stream):
|
17
|
+
self.__stream = stream
|
18
|
+
|
19
|
+
def __iter__ (self):
|
20
|
+
return self
|
21
|
+
|
22
|
+
def __next__ (self) -> Prediction:
|
23
|
+
prediction = c_void_p()
|
24
|
+
status = get_fxnc().FXNPredictionStreamReadNext(self.__stream, byref(prediction))
|
25
|
+
if status == FXNStatus.ERROR_INVALID_OPERATION:
|
26
|
+
raise StopIteration()
|
27
|
+
elif status != FXNStatus.OK:
|
28
|
+
raise RuntimeError(f"Failed to read next prediction in stream with error: {status_to_error(status)}")
|
29
|
+
else:
|
30
|
+
return Prediction(prediction)
|
31
|
+
|
32
|
+
def __enter__ (self):
|
33
|
+
return self
|
34
|
+
|
35
|
+
def __exit__ (self, exc_type, exc_value, traceback):
|
36
|
+
self.__release()
|
37
|
+
|
38
|
+
def __release (self):
|
39
|
+
if self.__stream:
|
40
|
+
get_fxnc().FXNPredictionStreamRelease(self.__stream)
|
41
|
+
self.__stream = None
|