singlestoredb 1.12.4__cp38-abi3-win_amd64.whl → 1.13.1__cp38-abi3-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.
Potentially problematic release.
This version of singlestoredb might be problematic. Click here for more details.
- _singlestoredb_accel.pyd +0 -0
- singlestoredb/__init__.py +1 -1
- singlestoredb/ai/__init__.py +1 -0
- singlestoredb/ai/chat.py +26 -0
- singlestoredb/ai/embeddings.py +18 -15
- singlestoredb/apps/__init__.py +1 -0
- singlestoredb/apps/_config.py +6 -0
- singlestoredb/apps/_connection_info.py +8 -0
- singlestoredb/apps/_python_udfs.py +85 -0
- singlestoredb/config.py +14 -2
- singlestoredb/functions/__init__.py +15 -1
- singlestoredb/functions/decorator.py +102 -252
- singlestoredb/functions/dtypes.py +545 -198
- singlestoredb/functions/ext/asgi.py +421 -129
- singlestoredb/functions/ext/json.py +29 -36
- singlestoredb/functions/ext/mmap.py +1 -1
- singlestoredb/functions/ext/rowdat_1.py +50 -70
- singlestoredb/functions/signature.py +816 -144
- singlestoredb/functions/typing.py +41 -0
- singlestoredb/functions/utils.py +421 -0
- singlestoredb/http/connection.py +3 -1
- singlestoredb/management/inference_api.py +101 -0
- singlestoredb/management/manager.py +6 -1
- singlestoredb/management/organization.py +17 -0
- singlestoredb/management/utils.py +2 -2
- singlestoredb/tests/ext_funcs/__init__.py +476 -237
- singlestoredb/tests/test_ext_func.py +192 -3
- singlestoredb/tests/test_management.py +5 -5
- singlestoredb/tests/test_udf.py +101 -131
- singlestoredb/tests/test_udf_returns.py +459 -0
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/METADATA +2 -1
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/RECORD +36 -30
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/LICENSE +0 -0
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/WHEEL +0 -0
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/entry_points.txt +0 -0
- {singlestoredb-1.12.4.dist-info → singlestoredb-1.13.1.dist-info}/top_level.txt +0 -0
_singlestoredb_accel.pyd
CHANGED
|
Binary file
|
singlestoredb/__init__.py
CHANGED
singlestoredb/ai/__init__.py
CHANGED
singlestoredb/ai/chat.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from singlestoredb.fusion.handlers.utils import get_workspace_manager
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
from langchain_openai import ChatOpenAI
|
|
8
|
+
except ImportError:
|
|
9
|
+
raise ImportError(
|
|
10
|
+
'Could not import langchain_openai python package. '
|
|
11
|
+
'Please install it with `pip install langchain_openai`.',
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SingleStoreChatOpenAI(ChatOpenAI):
|
|
16
|
+
def __init__(self, model_name: str, **kwargs: Any):
|
|
17
|
+
inference_api_manger = (
|
|
18
|
+
get_workspace_manager().organizations.current.inference_apis
|
|
19
|
+
)
|
|
20
|
+
info = inference_api_manger.get(model_name=model_name)
|
|
21
|
+
super().__init__(
|
|
22
|
+
base_url=info.connection_url,
|
|
23
|
+
api_key=os.environ.get('SINGLESTOREDB_USER_TOKEN'),
|
|
24
|
+
model=model_name,
|
|
25
|
+
**kwargs,
|
|
26
|
+
)
|
singlestoredb/ai/embeddings.py
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
import os
|
|
1
|
+
import os
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
|
+
from singlestoredb.fusion.handlers.utils import get_workspace_manager
|
|
5
|
+
|
|
4
6
|
try:
|
|
5
|
-
from
|
|
7
|
+
from langchain_openai import OpenAIEmbeddings
|
|
6
8
|
except ImportError:
|
|
7
9
|
raise ImportError(
|
|
8
|
-
'Could not import
|
|
9
|
-
'Please install it with `pip install
|
|
10
|
+
'Could not import langchain_openai python package. '
|
|
11
|
+
'Please install it with `pip install langchain_openai`.',
|
|
10
12
|
)
|
|
11
13
|
|
|
12
14
|
|
|
13
|
-
class SingleStoreEmbeddings(
|
|
14
|
-
|
|
15
|
-
def __init__(self, **kwargs: Any):
|
|
16
|
-
url = _os.getenv('SINGLESTORE_AI_EXPERIMENTAL_URL')
|
|
17
|
-
if not url:
|
|
18
|
-
raise ValueError(
|
|
19
|
-
"Environment variable 'SINGLESTORE_AI_EXPERIMENTAL_URL' must be set",
|
|
20
|
-
)
|
|
15
|
+
class SingleStoreEmbeddings(OpenAIEmbeddings):
|
|
21
16
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
def __init__(self, model_name: str, **kwargs: Any):
|
|
18
|
+
inference_api_manger = (
|
|
19
|
+
get_workspace_manager().organizations.current.inference_apis
|
|
20
|
+
)
|
|
21
|
+
info = inference_api_manger.get(model_name=model_name)
|
|
22
|
+
super().__init__(
|
|
23
|
+
base_url=info.connection_url,
|
|
24
|
+
api_key=os.environ.get('SINGLESTOREDB_USER_TOKEN'),
|
|
25
|
+
model=model_name,
|
|
26
|
+
**kwargs,
|
|
27
|
+
)
|
singlestoredb/apps/__init__.py
CHANGED
singlestoredb/apps/_config.py
CHANGED
|
@@ -8,10 +8,12 @@ class AppConfig:
|
|
|
8
8
|
listen_port: int
|
|
9
9
|
base_url: str
|
|
10
10
|
base_path: str
|
|
11
|
+
notebook_server_id: str
|
|
11
12
|
app_token: Optional[str]
|
|
12
13
|
user_token: Optional[str]
|
|
13
14
|
running_interactively: bool
|
|
14
15
|
is_gateway_enabled: bool
|
|
16
|
+
is_local_dev: bool
|
|
15
17
|
|
|
16
18
|
@staticmethod
|
|
17
19
|
def _read_variable(name: str) -> str:
|
|
@@ -28,6 +30,8 @@ class AppConfig:
|
|
|
28
30
|
port = cls._read_variable('SINGLESTOREDB_APP_LISTEN_PORT')
|
|
29
31
|
base_url = cls._read_variable('SINGLESTOREDB_APP_BASE_URL')
|
|
30
32
|
base_path = cls._read_variable('SINGLESTOREDB_APP_BASE_PATH')
|
|
33
|
+
notebook_server_id = cls._read_variable('SINGLESTOREDB_NOTEBOOK_SERVER_ID')
|
|
34
|
+
is_local_dev_env_var = cls._read_variable('SINGLESTOREDB_IS_LOCAL_DEV')
|
|
31
35
|
|
|
32
36
|
workload_type = os.environ.get('SINGLESTOREDB_WORKLOAD_TYPE')
|
|
33
37
|
running_interactively = workload_type == 'InteractiveNotebook'
|
|
@@ -49,10 +53,12 @@ class AppConfig:
|
|
|
49
53
|
listen_port=int(port),
|
|
50
54
|
base_url=base_url,
|
|
51
55
|
base_path=base_path,
|
|
56
|
+
notebook_server_id=notebook_server_id,
|
|
52
57
|
app_token=app_token,
|
|
53
58
|
user_token=user_token,
|
|
54
59
|
running_interactively=running_interactively,
|
|
55
60
|
is_gateway_enabled=is_gateway_enabled,
|
|
61
|
+
is_local_dev=is_local_dev_env_var == 'true',
|
|
56
62
|
)
|
|
57
63
|
|
|
58
64
|
@property
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
+
from typing import Any
|
|
3
|
+
from typing import Dict
|
|
2
4
|
from typing import Optional
|
|
3
5
|
|
|
4
6
|
|
|
@@ -8,3 +10,9 @@ class ConnectionInfo:
|
|
|
8
10
|
|
|
9
11
|
# Only present in interactive mode
|
|
10
12
|
token: Optional[str]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class UdfConnectionInfo:
|
|
17
|
+
url: str
|
|
18
|
+
functions: Dict[str, Any]
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import os
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
from ..functions.ext.asgi import Application
|
|
6
|
+
from ._config import AppConfig
|
|
7
|
+
from ._connection_info import UdfConnectionInfo
|
|
8
|
+
from ._process import kill_process_by_port
|
|
9
|
+
|
|
10
|
+
if typing.TYPE_CHECKING:
|
|
11
|
+
from ._uvicorn_util import AwaitableUvicornServer
|
|
12
|
+
|
|
13
|
+
# Keep track of currently running server
|
|
14
|
+
_running_server: 'typing.Optional[AwaitableUvicornServer]' = None
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
async def run_udf_app(
|
|
18
|
+
replace_existing: bool,
|
|
19
|
+
log_level: str = 'error',
|
|
20
|
+
kill_existing_app_server: bool = True,
|
|
21
|
+
) -> UdfConnectionInfo:
|
|
22
|
+
global _running_server
|
|
23
|
+
from ._uvicorn_util import AwaitableUvicornServer
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
import uvicorn
|
|
27
|
+
except ImportError:
|
|
28
|
+
raise ImportError('package uvicorn is required to run python udfs')
|
|
29
|
+
|
|
30
|
+
app_config = AppConfig.from_env()
|
|
31
|
+
|
|
32
|
+
if kill_existing_app_server:
|
|
33
|
+
# Shutdown the server gracefully if it was started by us.
|
|
34
|
+
# Since the uvicorn server doesn't start a new subprocess
|
|
35
|
+
# killing the process would result in kernel dying.
|
|
36
|
+
if _running_server is not None:
|
|
37
|
+
await _running_server.shutdown()
|
|
38
|
+
_running_server = None
|
|
39
|
+
|
|
40
|
+
# Kill if any other process is occupying the port
|
|
41
|
+
kill_process_by_port(app_config.listen_port)
|
|
42
|
+
|
|
43
|
+
base_url = generate_base_url(app_config)
|
|
44
|
+
|
|
45
|
+
udf_suffix = ''
|
|
46
|
+
if app_config.running_interactively:
|
|
47
|
+
udf_suffix = '_test'
|
|
48
|
+
app = Application(url=base_url, app_mode='managed', name_suffix=udf_suffix)
|
|
49
|
+
|
|
50
|
+
config = uvicorn.Config(
|
|
51
|
+
app,
|
|
52
|
+
host='0.0.0.0',
|
|
53
|
+
port=app_config.listen_port,
|
|
54
|
+
log_level=log_level,
|
|
55
|
+
)
|
|
56
|
+
_running_server = AwaitableUvicornServer(config)
|
|
57
|
+
|
|
58
|
+
# Register the functions
|
|
59
|
+
app.register_functions(replace=replace_existing)
|
|
60
|
+
|
|
61
|
+
asyncio.create_task(_running_server.serve())
|
|
62
|
+
await _running_server.wait_for_startup()
|
|
63
|
+
|
|
64
|
+
print(f'Python UDF registered at {base_url}')
|
|
65
|
+
|
|
66
|
+
return UdfConnectionInfo(base_url, app.get_function_info())
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def generate_base_url(app_config: AppConfig) -> str:
|
|
70
|
+
if not app_config.is_gateway_enabled:
|
|
71
|
+
raise RuntimeError('Python UDFs are not available if Nova Gateway is not enabled')
|
|
72
|
+
|
|
73
|
+
if not app_config.running_interactively:
|
|
74
|
+
return app_config.base_url
|
|
75
|
+
|
|
76
|
+
# generate python udf endpoint for interactive notebooks
|
|
77
|
+
gateway_url = os.environ.get('SINGLESTOREDB_NOVA_GATEWAY_ENDPOINT')
|
|
78
|
+
if app_config.is_local_dev:
|
|
79
|
+
gateway_url = os.environ.get('SINGLESTOREDB_NOVA_GATEWAY_DEV_ENDPOINT')
|
|
80
|
+
if gateway_url is None:
|
|
81
|
+
raise RuntimeError(
|
|
82
|
+
'Missing SINGLESTOREDB_NOVA_GATEWAY_DEV_ENDPOINT environment variable.',
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
return f'{gateway_url}/pythonudfs/{app_config.notebook_server_id}/interactive/'
|
singlestoredb/config.py
CHANGED
|
@@ -317,7 +317,7 @@ register_option(
|
|
|
317
317
|
'external_function.app_mode', 'string',
|
|
318
318
|
functools.partial(
|
|
319
319
|
check_str,
|
|
320
|
-
valid_values=['remote', 'collocated'],
|
|
320
|
+
valid_values=['remote', 'collocated', 'managed'],
|
|
321
321
|
),
|
|
322
322
|
'remote',
|
|
323
323
|
'Specifies the mode of operation of the external function application.',
|
|
@@ -407,6 +407,18 @@ register_option(
|
|
|
407
407
|
environ=['SINGLESTOREDB_EXT_FUNC_LOG_LEVEL'],
|
|
408
408
|
)
|
|
409
409
|
|
|
410
|
+
register_option(
|
|
411
|
+
'external_function.name_prefix', 'string', check_str, '',
|
|
412
|
+
'Prefix to add to external function names.',
|
|
413
|
+
environ=['SINGLESTOREDB_EXT_FUNC_NAME_PREFIX'],
|
|
414
|
+
)
|
|
415
|
+
|
|
416
|
+
register_option(
|
|
417
|
+
'external_function.name_suffix', 'string', check_str, '',
|
|
418
|
+
'Suffix to add to external function names.',
|
|
419
|
+
environ=['SINGLESTOREDB_EXT_FUNC_NAME_SUFFIX'],
|
|
420
|
+
)
|
|
421
|
+
|
|
410
422
|
register_option(
|
|
411
423
|
'external_function.connection', 'string', check_str,
|
|
412
424
|
os.environ.get('SINGLESTOREDB_URL') or None,
|
|
@@ -415,7 +427,7 @@ register_option(
|
|
|
415
427
|
)
|
|
416
428
|
|
|
417
429
|
register_option(
|
|
418
|
-
'external_function.host', 'string', check_str, '
|
|
430
|
+
'external_function.host', 'string', check_str, 'localhost',
|
|
419
431
|
'Specifies the host to bind the server to.',
|
|
420
432
|
environ=['SINGLESTOREDB_EXT_FUNC_HOST'],
|
|
421
433
|
)
|
|
@@ -1,2 +1,16 @@
|
|
|
1
|
-
from .decorator import tvf # noqa: F401
|
|
2
1
|
from .decorator import udf # noqa: F401
|
|
2
|
+
from .typing import Masked # noqa: F401
|
|
3
|
+
from .typing import Table # noqa: F401
|
|
4
|
+
from .utils import pack_vector # noqa: F401
|
|
5
|
+
from .utils import pack_vectors # noqa: F401
|
|
6
|
+
from .utils import unpack_vector # noqa: F401
|
|
7
|
+
from .utils import unpack_vectors # noqa: F401
|
|
8
|
+
from .utils import VectorTypes
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
F32 = VectorTypes.F32
|
|
12
|
+
F64 = VectorTypes.F64
|
|
13
|
+
I8 = VectorTypes.I8
|
|
14
|
+
I16 = VectorTypes.I16
|
|
15
|
+
I32 = VectorTypes.I32
|
|
16
|
+
I64 = VectorTypes.I64
|