singlestoredb 1.13.0__cp38-abi3-win32.whl → 1.14.0__cp38-abi3-win32.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 CHANGED
Binary file
singlestoredb/__init__.py CHANGED
@@ -13,7 +13,7 @@ Examples
13
13
 
14
14
  """
15
15
 
16
- __version__ = '1.13.0'
16
+ __version__ = '1.14.0'
17
17
 
18
18
  from typing import Any
19
19
 
@@ -31,6 +31,14 @@ from .types import (
31
31
  Date, Time, Timestamp, DateFromTicks, TimeFromTicks, TimestampFromTicks,
32
32
  Binary, STRING, BINARY, NUMBER, DATETIME, ROWID,
33
33
  )
34
+ from .vectorstore import (
35
+ vector_db, IndexInterface, IndexList, IndexModel, MatchTypedDict,
36
+ Metric, IndexStatsTypedDict, NamespaceStatsTypedDict, Vector,
37
+ VectorDictMetadataValue, VectorMetadataTypedDict, VectorTuple,
38
+ VectorTupleWithMetadata, DeletionProtection, AndFilter, EqFilter,
39
+ ExactMatchFilter, FilterTypedDict, GteFilter, GtFilter, InFilter,
40
+ LteFilter, LtFilter, NeFilter, NinFilter, OrFilter, SimpleFilter,
41
+ )
34
42
 
35
43
 
36
44
  #
@@ -1 +1,2 @@
1
+ from .chat import SingleStoreChatOpenAI # noqa: F401
1
2
  from .embeddings import SingleStoreEmbeddings # noqa: F401
@@ -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
+ )
@@ -1,24 +1,27 @@
1
- import os as _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 langchain_community.embeddings.ollama import OllamaEmbeddings
7
+ from langchain_openai import OpenAIEmbeddings
6
8
  except ImportError:
7
9
  raise ImportError(
8
- 'Could not import langchain_community python package. '
9
- 'Please install it with `pip install langchain_community`.',
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(OllamaEmbeddings):
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
- base_url = url.strip('/v1')
23
- kwargs = {'model': 'nomic-embed-text', **kwargs}
24
- super().__init__(base_url=base_url, **kwargs)
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
+ )
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  """SingleStoreDB connections and cursors."""
3
3
  import abc
4
+ import functools
4
5
  import inspect
5
6
  import io
6
7
  import queue
@@ -1288,6 +1289,14 @@ class Connection(metaclass=abc.ABCMeta):
1288
1289
  """Access server properties managed by the SHOW statement."""
1289
1290
  return ShowAccessor(self)
1290
1291
 
1292
+ @functools.cached_property
1293
+ def vector_db(self) -> Any:
1294
+ """
1295
+ Get vectorstore API accessor
1296
+ """
1297
+ from vectorstore import VectorDB
1298
+ return VectorDB(connection=self)
1299
+
1291
1300
 
1292
1301
  #
1293
1302
  # NOTE: When adding parameters to this function, you should always
@@ -1,6 +1,10 @@
1
1
  from .decorator import udf # noqa: F401
2
2
  from .typing import Masked # noqa: F401
3
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
4
8
  from .utils import VectorTypes
5
9
 
6
10
 
@@ -246,6 +246,192 @@ def get_masked_params(func: Callable[..., Any]) -> List[bool]:
246
246
  return [typing.get_origin(x.annotation) is Masked for x in params.values()]
247
247
 
248
248
 
249
+ def build_tuple(x: Any) -> Any:
250
+ """Convert object to tuple."""
251
+ return tuple(x) if isinstance(x, Masked) else (x, None)
252
+
253
+
254
+ def build_udf_endpoint(
255
+ func: Callable[..., Any],
256
+ returns_data_format: str,
257
+ ) -> Callable[..., Any]:
258
+ """
259
+ Build a UDF endpoint for scalar / list types (row-based).
260
+
261
+ Parameters
262
+ ----------
263
+ func : Callable
264
+ The function to call as the endpoint
265
+ returns_data_format : str
266
+ The format of the return values
267
+
268
+ Returns
269
+ -------
270
+ Callable
271
+ The function endpoint
272
+
273
+ """
274
+ if returns_data_format in ['scalar', 'list']:
275
+
276
+ async def do_func(
277
+ row_ids: Sequence[int],
278
+ rows: Sequence[Sequence[Any]],
279
+ ) -> Tuple[Sequence[int], List[Tuple[Any, ...]]]:
280
+ '''Call function on given rows of data.'''
281
+ return row_ids, [as_tuple(x) for x in zip(func_map(func, rows))]
282
+
283
+ return do_func
284
+
285
+ return build_vector_udf_endpoint(func, returns_data_format)
286
+
287
+
288
+ def build_vector_udf_endpoint(
289
+ func: Callable[..., Any],
290
+ returns_data_format: str,
291
+ ) -> Callable[..., Any]:
292
+ """
293
+ Build a UDF endpoint for vector formats (column-based).
294
+
295
+ Parameters
296
+ ----------
297
+ func : Callable
298
+ The function to call as the endpoint
299
+ returns_data_format : str
300
+ The format of the return values
301
+
302
+ Returns
303
+ -------
304
+ Callable
305
+ The function endpoint
306
+
307
+ """
308
+ masks = get_masked_params(func)
309
+ array_cls = get_array_class(returns_data_format)
310
+
311
+ async def do_func(
312
+ row_ids: Sequence[int],
313
+ cols: Sequence[Tuple[Sequence[Any], Optional[Sequence[bool]]]],
314
+ ) -> Tuple[
315
+ Sequence[int],
316
+ List[Tuple[Sequence[Any], Optional[Sequence[bool]]]],
317
+ ]:
318
+ '''Call function on given columns of data.'''
319
+ row_ids = array_cls(row_ids)
320
+
321
+ # Call the function with `cols` as the function parameters
322
+ if cols and cols[0]:
323
+ out = func(*[x if m else x[0] for x, m in zip(cols, masks)])
324
+ else:
325
+ out = func()
326
+
327
+ # Single masked value
328
+ if isinstance(out, Masked):
329
+ return row_ids, [tuple(out)]
330
+
331
+ # Multiple return values
332
+ if isinstance(out, tuple):
333
+ return row_ids, [build_tuple(x) for x in out]
334
+
335
+ # Single return value
336
+ return row_ids, [(out, None)]
337
+
338
+ return do_func
339
+
340
+
341
+ def build_tvf_endpoint(
342
+ func: Callable[..., Any],
343
+ returns_data_format: str,
344
+ ) -> Callable[..., Any]:
345
+ """
346
+ Build a TVF endpoint for scalar / list types (row-based).
347
+
348
+ Parameters
349
+ ----------
350
+ func : Callable
351
+ The function to call as the endpoint
352
+ returns_data_format : str
353
+ The format of the return values
354
+
355
+ Returns
356
+ -------
357
+ Callable
358
+ The function endpoint
359
+
360
+ """
361
+ if returns_data_format in ['scalar', 'list']:
362
+
363
+ async def do_func(
364
+ row_ids: Sequence[int],
365
+ rows: Sequence[Sequence[Any]],
366
+ ) -> Tuple[Sequence[int], List[Tuple[Any, ...]]]:
367
+ '''Call function on given rows of data.'''
368
+ out_ids: List[int] = []
369
+ out = []
370
+ # Call function on each row of data
371
+ for i, res in zip(row_ids, func_map(func, rows)):
372
+ out.extend(as_list_of_tuples(res))
373
+ out_ids.extend([row_ids[i]] * (len(out)-len(out_ids)))
374
+ return out_ids, out
375
+
376
+ return do_func
377
+
378
+ return build_vector_tvf_endpoint(func, returns_data_format)
379
+
380
+
381
+ def build_vector_tvf_endpoint(
382
+ func: Callable[..., Any],
383
+ returns_data_format: str,
384
+ ) -> Callable[..., Any]:
385
+ """
386
+ Build a TVF endpoint for vector formats (column-based).
387
+
388
+ Parameters
389
+ ----------
390
+ func : Callable
391
+ The function to call as the endpoint
392
+ returns_data_format : str
393
+ The format of the return values
394
+
395
+ Returns
396
+ -------
397
+ Callable
398
+ The function endpoint
399
+
400
+ """
401
+ masks = get_masked_params(func)
402
+ array_cls = get_array_class(returns_data_format)
403
+
404
+ async def do_func(
405
+ row_ids: Sequence[int],
406
+ cols: Sequence[Tuple[Sequence[Any], Optional[Sequence[bool]]]],
407
+ ) -> Tuple[
408
+ Sequence[int],
409
+ List[Tuple[Sequence[Any], Optional[Sequence[bool]]]],
410
+ ]:
411
+ '''Call function on given columns of data.'''
412
+ # NOTE: There is no way to determine which row ID belongs to
413
+ # each result row, so we just have to use the same
414
+ # row ID for all rows in the result.
415
+
416
+ # Call function on each column of data
417
+ if cols and cols[0]:
418
+ res = get_dataframe_columns(
419
+ func(*[x if m else x[0] for x, m in zip(cols, masks)]),
420
+ )
421
+ else:
422
+ res = get_dataframe_columns(func())
423
+
424
+ # Generate row IDs
425
+ if isinstance(res[0], Masked):
426
+ row_ids = array_cls([row_ids[0]] * len(res[0][0]))
427
+ else:
428
+ row_ids = array_cls([row_ids[0]] * len(res[0]))
429
+
430
+ return row_ids, [build_tuple(x) for x in res]
431
+
432
+ return do_func
433
+
434
+
249
435
  def make_func(
250
436
  name: str,
251
437
  func: Callable[..., Any],
@@ -273,102 +459,10 @@ def make_func(
273
459
  args_data_format = sig.get('args_data_format', 'scalar')
274
460
  returns_data_format = sig.get('returns_data_format', 'scalar')
275
461
 
276
- masks = get_masked_params(func)
277
-
278
462
  if function_type == 'tvf':
279
- # Scalar / list types (row-based)
280
- if returns_data_format in ['scalar', 'list']:
281
- async def do_func(
282
- row_ids: Sequence[int],
283
- rows: Sequence[Sequence[Any]],
284
- ) -> Tuple[Sequence[int], List[Tuple[Any, ...]]]:
285
- '''Call function on given rows of data.'''
286
- out_ids: List[int] = []
287
- out = []
288
- # Call function on each row of data
289
- for i, res in zip(row_ids, func_map(func, rows)):
290
- out.extend(as_list_of_tuples(res))
291
- out_ids.extend([row_ids[i]] * (len(out)-len(out_ids)))
292
- return out_ids, out
293
-
294
- # Vector formats (column-based)
295
- else:
296
- array_cls = get_array_class(returns_data_format)
297
-
298
- async def do_func( # type: ignore
299
- row_ids: Sequence[int],
300
- cols: Sequence[Tuple[Sequence[Any], Optional[Sequence[bool]]]],
301
- ) -> Tuple[
302
- Sequence[int],
303
- List[Tuple[Sequence[Any], Optional[Sequence[bool]]]],
304
- ]:
305
- '''Call function on given cols of data.'''
306
- # NOTE: There is no way to determine which row ID belongs to
307
- # each result row, so we just have to use the same
308
- # row ID for all rows in the result.
309
-
310
- def build_tuple(x: Any) -> Any:
311
- return tuple(x) if isinstance(x, Masked) else (x, None)
312
-
313
- # Call function on each column of data
314
- if cols and cols[0]:
315
- res = get_dataframe_columns(
316
- func(*[x if m else x[0] for x, m in zip(cols, masks)]),
317
- )
318
- else:
319
- res = get_dataframe_columns(func())
320
-
321
- # Generate row IDs
322
- if isinstance(res[0], Masked):
323
- row_ids = array_cls([row_ids[0]] * len(res[0][0]))
324
- else:
325
- row_ids = array_cls([row_ids[0]] * len(res[0]))
326
-
327
- return row_ids, [build_tuple(x) for x in res]
328
-
463
+ do_func = build_tvf_endpoint(func, returns_data_format)
329
464
  else:
330
- # Scalar / list types (row-based)
331
- if returns_data_format in ['scalar', 'list']:
332
- async def do_func(
333
- row_ids: Sequence[int],
334
- rows: Sequence[Sequence[Any]],
335
- ) -> Tuple[Sequence[int], List[Tuple[Any, ...]]]:
336
- '''Call function on given rows of data.'''
337
- return row_ids, [as_tuple(x) for x in zip(func_map(func, rows))]
338
-
339
- # Vector formats (column-based)
340
- else:
341
- array_cls = get_array_class(returns_data_format)
342
-
343
- async def do_func( # type: ignore
344
- row_ids: Sequence[int],
345
- cols: Sequence[Tuple[Sequence[Any], Optional[Sequence[bool]]]],
346
- ) -> Tuple[
347
- Sequence[int],
348
- List[Tuple[Sequence[Any], Optional[Sequence[bool]]]],
349
- ]:
350
- '''Call function on given cols of data.'''
351
- row_ids = array_cls(row_ids)
352
-
353
- def build_tuple(x: Any) -> Any:
354
- return tuple(x) if isinstance(x, Masked) else (x, None)
355
-
356
- # Call the function with `cols` as the function parameters
357
- if cols and cols[0]:
358
- out = func(*[x if m else x[0] for x, m in zip(cols, masks)])
359
- else:
360
- out = func()
361
-
362
- # Single masked value
363
- if isinstance(out, Masked):
364
- return row_ids, [tuple(out)]
365
-
366
- # Multiple return values
367
- if isinstance(out, tuple):
368
- return row_ids, [build_tuple(x) for x in out]
369
-
370
- # Single return value
371
- return row_ids, [(out, None)]
465
+ do_func = build_udf_endpoint(func, returns_data_format)
372
466
 
373
467
  do_func.__name__ = name
374
468
  do_func.__doc__ = func.__doc__
@@ -8,6 +8,8 @@ from enum import Enum
8
8
  from typing import Any
9
9
  from typing import Dict
10
10
  from typing import Iterable
11
+ from typing import Tuple
12
+ from typing import Union
11
13
 
12
14
  from .typing import Masked
13
15
 
@@ -192,151 +194,228 @@ class VectorTypes(str, Enum):
192
194
  I64 = 'i64'
193
195
 
194
196
 
197
+ def _vector_type_to_numpy_type(
198
+ vector_type: VectorTypes,
199
+ ) -> str:
200
+ """Convert a vector type to a numpy type."""
201
+ if vector_type == VectorTypes.F32:
202
+ return 'f4'
203
+ elif vector_type == VectorTypes.F64:
204
+ return 'f8'
205
+ elif vector_type == VectorTypes.I8:
206
+ return 'i1'
207
+ elif vector_type == VectorTypes.I16:
208
+ return 'i2'
209
+ elif vector_type == VectorTypes.I32:
210
+ return 'i4'
211
+ elif vector_type == VectorTypes.I64:
212
+ return 'i8'
213
+ raise ValueError(f'unsupported element type: {vector_type}')
214
+
215
+
216
+ def _vector_type_to_struct_format(
217
+ vec: Any,
218
+ vector_type: VectorTypes,
219
+ ) -> str:
220
+ """Convert a vector type to a struct format string."""
221
+ n = len(vec)
222
+ if vector_type == VectorTypes.F32:
223
+ if isinstance(vec, (bytes, bytearray)):
224
+ n = n // 4
225
+ return f'<{n}f'
226
+ elif vector_type == VectorTypes.F64:
227
+ if isinstance(vec, (bytes, bytearray)):
228
+ n = n // 8
229
+ return f'<{n}d'
230
+ elif vector_type == VectorTypes.I8:
231
+ return f'<{n}b'
232
+ elif vector_type == VectorTypes.I16:
233
+ if isinstance(vec, (bytes, bytearray)):
234
+ n = n // 2
235
+ return f'<{n}h'
236
+ elif vector_type == VectorTypes.I32:
237
+ if isinstance(vec, (bytes, bytearray)):
238
+ n = n // 4
239
+ return f'<{n}i'
240
+ elif vector_type == VectorTypes.I64:
241
+ if isinstance(vec, (bytes, bytearray)):
242
+ n = n // 8
243
+ return f'<{n}q'
244
+ raise ValueError(f'unsupported element type: {vector_type}')
245
+
246
+
195
247
  def unpack_vector(
196
- obj: Any,
197
- element_type: VectorTypes = VectorTypes.F32,
198
- ) -> Iterable[Any]:
248
+ obj: Union[bytes, bytearray],
249
+ vec_type: VectorTypes = VectorTypes.F32,
250
+ ) -> Tuple[Any]:
199
251
  """
200
252
  Unpack a vector from bytes.
201
253
 
202
254
  Parameters
203
255
  ----------
204
- obj : Any
256
+ obj : bytes or bytearray
205
257
  The object to unpack.
206
- element_type : VectorTypes
258
+ vec_type : VectorTypes
207
259
  The type of the elements in the vector.
208
260
  Can be one of 'f32', 'f64', 'i8', 'i16', 'i32', or 'i64'.
209
261
  Default is 'f32'.
210
262
 
211
263
  Returns
212
264
  -------
213
- Iterable[Any]
265
+ Tuple[Any]
214
266
  The unpacked vector.
215
267
 
216
268
  """
217
- if isinstance(obj, (bytes, bytearray, list, tuple)):
218
- if element_type == 'f32':
219
- n = len(obj) // 4
220
- fmt = 'f'
221
- elif element_type == 'f64':
222
- n = len(obj) // 8
223
- fmt = 'd'
224
- elif element_type == 'i8':
225
- n = len(obj)
226
- fmt = 'b'
227
- elif element_type == 'i16':
228
- n = len(obj) // 2
229
- fmt = 'h'
230
- elif element_type == 'i32':
231
- n = len(obj) // 4
232
- fmt = 'i'
233
- elif element_type == 'i64':
234
- n = len(obj) // 8
235
- fmt = 'q'
236
- else:
237
- raise ValueError(f'unsupported element type: {element_type}')
238
-
239
- if isinstance(obj, (bytes, bytearray)):
240
- return struct.unpack(f'<{n}{fmt}', obj)
241
- return tuple([struct.unpack(f'<{n}{fmt}', x) for x in obj])
242
-
243
- if element_type == 'f32':
244
- np_type = 'f4'
245
- elif element_type == 'f64':
246
- np_type = 'f8'
247
- elif element_type == 'i8':
248
- np_type = 'i1'
249
- elif element_type == 'i16':
250
- np_type = 'i2'
251
- elif element_type == 'i32':
252
- np_type = 'i4'
253
- elif element_type == 'i64':
254
- np_type = 'i8'
255
- else:
256
- raise ValueError(f'unsupported element type: {element_type}')
269
+ return struct.unpack(_vector_type_to_struct_format(obj, vec_type), obj)
270
+
271
+
272
+ def pack_vector(
273
+ obj: Any,
274
+ vec_type: VectorTypes = VectorTypes.F32,
275
+ ) -> bytes:
276
+ """
277
+ Pack a vector into bytes.
278
+
279
+ Parameters
280
+ ----------
281
+ obj : Any
282
+ The object to pack.
283
+ vec_type : VectorTypes
284
+ The type of the elements in the vector.
285
+ Can be one of 'f32', 'f64', 'i8', 'i16', 'i32', or 'i64'.
286
+ Default is 'f32'.
287
+
288
+ Returns
289
+ -------
290
+ bytes
291
+ The packed vector.
292
+
293
+ """
294
+ if isinstance(obj, (list, tuple)):
295
+ return struct.pack(_vector_type_to_struct_format(obj, vec_type), *obj)
257
296
 
258
297
  if is_numpy(obj):
259
- import numpy as np
260
- return np.array([np.frombuffer(x, dtype=np_type) for x in obj])
298
+ return obj.tobytes()
261
299
 
262
300
  if is_pandas_series(obj):
263
- import numpy as np
264
301
  import pandas as pd
265
- return pd.Series([np.frombuffer(x, dtype=np_type) for x in obj])
302
+ return pd.Series(obj).to_numpy().tobytes()
266
303
 
267
304
  if is_polars_series(obj):
268
- import numpy as np
269
305
  import polars as pl
270
- return pl.Series([np.frombuffer(x, dtype=np_type) for x in obj])
306
+ return pl.Series(obj).to_numpy().tobytes()
271
307
 
272
308
  if is_pyarrow_array(obj):
273
- import numpy as np
274
309
  import pyarrow as pa
275
- return pa.array([np.frombuffer(x, dtype=np_type) for x in obj])
310
+ return pa.array(obj).to_numpy().tobytes()
276
311
 
277
312
  raise ValueError(
278
313
  f'unsupported object type: {type(obj)}',
279
314
  )
280
315
 
281
316
 
282
- def pack_vector(
283
- obj: Any,
284
- element_type: VectorTypes = VectorTypes.F32,
285
- ) -> bytes:
317
+ def unpack_vectors(
318
+ arr_of_vec: Any,
319
+ vec_type: VectorTypes = VectorTypes.F32,
320
+ ) -> Iterable[Any]:
286
321
  """
287
- Pack a vector into bytes.
322
+ Unpack a vector from an array of bytes.
288
323
 
289
324
  Parameters
290
325
  ----------
291
- obj : Any
292
- The object to pack.
293
- element_type : VectorTypes
326
+ arr_of_vec : Iterable[Any]
327
+ The array of bytes to unpack.
328
+ vec_type : VectorTypes
294
329
  The type of the elements in the vector.
295
330
  Can be one of 'f32', 'f64', 'i8', 'i16', 'i32', or 'i64'.
296
331
  Default is 'f32'.
297
332
 
298
333
  Returns
299
334
  -------
300
- bytes
301
- The packed vector.
335
+ Iterable[Any]
336
+ The unpacked vector.
302
337
 
303
338
  """
304
- if element_type == 'f32':
305
- fmt = 'f'
306
- elif element_type == 'f64':
307
- fmt = 'd'
308
- elif element_type == 'i8':
309
- fmt = 'b'
310
- elif element_type == 'i16':
311
- fmt = 'h'
312
- elif element_type == 'i32':
313
- fmt = 'i'
314
- elif element_type == 'i64':
315
- fmt = 'q'
316
- else:
317
- raise ValueError(f'unsupported element type: {element_type}')
339
+ if isinstance(arr_of_vec, (list, tuple)):
340
+ return [unpack_vector(x, vec_type) for x in arr_of_vec]
318
341
 
319
- if isinstance(obj, (list, tuple)):
320
- return struct.pack(f'<{len(obj)}{fmt}', *obj)
342
+ import numpy as np
321
343
 
322
- elif is_numpy(obj):
323
- return obj.tobytes()
344
+ dtype = _vector_type_to_numpy_type(vec_type)
324
345
 
325
- elif is_pandas_series(obj):
326
- # TODO: Nested vectors
346
+ np_arr = np.array(
347
+ [np.frombuffer(x, dtype=dtype) for x in arr_of_vec],
348
+ dtype=dtype,
349
+ )
350
+
351
+ if is_numpy(arr_of_vec):
352
+ return np_arr
353
+
354
+ if is_pandas_series(arr_of_vec):
327
355
  import pandas as pd
328
- return pd.Series(obj).to_numpy().tobytes()
356
+ return pd.Series(np_arr)
329
357
 
330
- elif is_polars_series(obj):
331
- # TODO: Nested vectors
358
+ if is_polars_series(arr_of_vec):
332
359
  import polars as pl
333
- return pl.Series(obj).to_numpy().tobytes()
360
+ return pl.Series(np_arr)
334
361
 
335
- elif is_pyarrow_array(obj):
336
- # TODO: Nested vectors
362
+ if is_pyarrow_array(arr_of_vec):
337
363
  import pyarrow as pa
338
- return pa.array(obj).to_numpy().tobytes()
364
+ return pa.array(np_arr)
339
365
 
340
366
  raise ValueError(
341
- f'unsupported object type: {type(obj)}',
367
+ f'unsupported object type: {type(arr_of_vec)}',
368
+ )
369
+
370
+
371
+ def pack_vectors(
372
+ arr_of_arr: Iterable[Any],
373
+ vec_type: VectorTypes = VectorTypes.F32,
374
+ ) -> Iterable[Any]:
375
+ """
376
+ Pack a vector into an array of bytes.
377
+
378
+ Parameters
379
+ ----------
380
+ arr_of_arr : Iterable[Any]
381
+ The array of bytes to pack.
382
+ vec_type : VectorTypes
383
+ The type of the elements in the vector.
384
+ Can be one of 'f32', 'f64', 'i8', 'i16', 'i32', or 'i64'.
385
+ Default is 'f32'.
386
+
387
+ Returns
388
+ -------
389
+ Iterable[Any]
390
+ The array of packed vectors.
391
+
392
+ """
393
+ if isinstance(arr_of_arr, (list, tuple)):
394
+ if not arr_of_arr:
395
+ return []
396
+ fmt = _vector_type_to_struct_format(arr_of_arr[0], vec_type)
397
+ return [struct.pack(fmt, x) for x in arr_of_arr]
398
+
399
+ import numpy as np
400
+
401
+ # Use object type because numpy truncates nulls at the end of fixed binary
402
+ np_arr = np.array([x.tobytes() for x in arr_of_arr], dtype=np.object_)
403
+
404
+ if is_numpy(arr_of_arr):
405
+ return np_arr
406
+
407
+ if is_pandas_series(arr_of_arr):
408
+ import pandas as pd
409
+ return pd.Series(np_arr)
410
+
411
+ if is_polars_series(arr_of_arr):
412
+ import polars as pl
413
+ return pl.Series(np_arr)
414
+
415
+ if is_pyarrow_array(arr_of_arr):
416
+ import pyarrow as pa
417
+ return pa.array(np_arr)
418
+
419
+ raise ValueError(
420
+ f'unsupported object type: {type(arr_of_arr)}',
342
421
  )
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env python
2
+ """SingleStoreDB Cloud Inference API."""
3
+ import os
4
+ from typing import Any
5
+ from typing import Dict
6
+ from typing import Optional
7
+
8
+ from .utils import vars_to_str
9
+ from singlestoredb.exceptions import ManagementError
10
+ from singlestoredb.management.manager import Manager
11
+
12
+
13
+ class InferenceAPIInfo(object):
14
+ """
15
+ Inference API definition.
16
+
17
+ This object is not directly instantiated. It is used in results
18
+ of API calls on the :class:`InferenceAPIManager`. See :meth:`InferenceAPIManager.get`.
19
+ """
20
+
21
+ service_id: str
22
+ model_name: str
23
+ name: str
24
+ connection_url: str
25
+ project_id: str
26
+
27
+ def __init__(
28
+ self,
29
+ service_id: str,
30
+ model_name: str,
31
+ name: str,
32
+ connection_url: str,
33
+ project_id: str,
34
+ ):
35
+ self.service_id = service_id
36
+ self.connection_url = connection_url
37
+ self.model_name = model_name
38
+ self.name = name
39
+ self.project_id = project_id
40
+
41
+ @classmethod
42
+ def from_dict(
43
+ cls,
44
+ obj: Dict[str, Any],
45
+ ) -> 'InferenceAPIInfo':
46
+ """
47
+ Construct a Inference API from a dictionary of values.
48
+
49
+ Parameters
50
+ ----------
51
+ obj : dict
52
+ Dictionary of values
53
+
54
+ Returns
55
+ -------
56
+ :class:`Job`
57
+
58
+ """
59
+ out = cls(
60
+ service_id=obj['serviceID'],
61
+ project_id=obj['projectID'],
62
+ model_name=obj['modelName'],
63
+ name=obj['name'],
64
+ connection_url=obj['connectionURL'],
65
+ )
66
+ return out
67
+
68
+ def __str__(self) -> str:
69
+ """Return string representation."""
70
+ return vars_to_str(self)
71
+
72
+ def __repr__(self) -> str:
73
+ """Return string representation."""
74
+ return str(self)
75
+
76
+
77
+ class InferenceAPIManager(object):
78
+ """
79
+ SingleStoreDB Inference APIs manager.
80
+
81
+ This class should be instantiated using :attr:`Organization.inference_apis`.
82
+
83
+ Parameters
84
+ ----------
85
+ manager : InferenceAPIManager, optional
86
+ The InferenceAPIManager the InferenceAPIManager belongs to
87
+
88
+ See Also
89
+ --------
90
+ :attr:`InferenceAPI`
91
+ """
92
+
93
+ def __init__(self, manager: Optional[Manager]):
94
+ self._manager = manager
95
+ self.project_id = os.environ.get('SINGLESTOREDB_PROJECT')
96
+
97
+ def get(self, model_name: str) -> InferenceAPIInfo:
98
+ if self._manager is None:
99
+ raise ManagementError(msg='Manager not initialized')
100
+ res = self._manager._get(f'inferenceapis/{self.project_id}/{model_name}').json()
101
+ return InferenceAPIInfo.from_dict(res)
@@ -7,6 +7,7 @@ from typing import Optional
7
7
  from typing import Union
8
8
 
9
9
  from ..exceptions import ManagementError
10
+ from .inference_api import InferenceAPIManager
10
11
  from .job import JobsManager
11
12
  from .manager import Manager
12
13
  from .utils import vars_to_str
@@ -207,3 +208,19 @@ class Organization(object):
207
208
  :class:`JobsManager`
208
209
  """
209
210
  return JobsManager(self._manager)
211
+
212
+ @property
213
+ def inference_apis(self) -> InferenceAPIManager:
214
+ """
215
+ Retrieve a SingleStoreDB inference api manager.
216
+
217
+ Parameters
218
+ ----------
219
+ manager : WorkspaceManager, optional
220
+ The WorkspaceManager the InferenceAPIManager belongs to
221
+
222
+ Returns
223
+ -------
224
+ :class:`InferenceAPIManager`
225
+ """
226
+ return InferenceAPIManager(self._manager)
@@ -35,7 +35,7 @@ class TestCluster(unittest.TestCase):
35
35
  cls.manager = s2.manage_cluster()
36
36
 
37
37
  us_regions = [x for x in cls.manager.regions if 'US' in x.name]
38
- cls.password = secrets.token_urlsafe(20) + '-x&'
38
+ cls.password = secrets.token_urlsafe(20) + '-x&$'
39
39
 
40
40
  cls.cluster = cls.manager.create_cluster(
41
41
  clean_name('cm-test-{}'.format(secrets.token_urlsafe(20)[:20])),
@@ -201,7 +201,7 @@ class TestWorkspace(unittest.TestCase):
201
201
  cls.manager = s2.manage_workspaces()
202
202
 
203
203
  us_regions = [x for x in cls.manager.regions if 'US' in x.name]
204
- cls.password = secrets.token_urlsafe(20)
204
+ cls.password = secrets.token_urlsafe(20) + '-x&$'
205
205
 
206
206
  name = clean_name(secrets.token_urlsafe(20)[:20])
207
207
 
@@ -375,7 +375,7 @@ class TestStage(unittest.TestCase):
375
375
  cls.manager = s2.manage_workspaces()
376
376
 
377
377
  us_regions = [x for x in cls.manager.regions if 'US' in x.name]
378
- cls.password = secrets.token_urlsafe(20)
378
+ cls.password = secrets.token_urlsafe(20) + '-x&$'
379
379
 
380
380
  name = clean_name(secrets.token_urlsafe(20)[:20])
381
381
 
@@ -839,7 +839,7 @@ class TestSecrets(unittest.TestCase):
839
839
  cls.manager = s2.manage_workspaces()
840
840
 
841
841
  us_regions = [x for x in cls.manager.regions if 'US' in x.name]
842
- cls.password = secrets.token_urlsafe(20)
842
+ cls.password = secrets.token_urlsafe(20) + '-x&$'
843
843
 
844
844
  name = clean_name(secrets.token_urlsafe(20)[:20])
845
845
 
@@ -898,7 +898,7 @@ class TestJob(unittest.TestCase):
898
898
  cls.manager = s2.manage_workspaces()
899
899
 
900
900
  us_regions = [x for x in cls.manager.regions if 'US' in x.name]
901
- cls.password = secrets.token_urlsafe(20)
901
+ cls.password = secrets.token_urlsafe(20) + '-x&$'
902
902
 
903
903
  name = clean_name(secrets.token_urlsafe(20)[:20])
904
904
 
@@ -0,0 +1,51 @@
1
+ import os
2
+ import unittest
3
+
4
+ from vectorstore import VectorDB
5
+
6
+ import singlestoredb as s2
7
+ from . import utils
8
+
9
+
10
+ class TestVectorDB(unittest.TestCase):
11
+
12
+ driver = s2
13
+
14
+ dbname: str = ''
15
+ dbexisted: bool = False
16
+
17
+ @classmethod
18
+ def setUpClass(cls) -> None:
19
+ sql_file = os.path.join(os.path.dirname(__file__), 'empty.sql')
20
+ cls.dbname, cls.dbexisted = utils.load_sql(sql_file) # type: ignore
21
+
22
+ @classmethod
23
+ def tearDownClass(cls) -> None:
24
+ if not cls.dbexisted:
25
+ utils.drop_database(cls.dbname) # type: ignore
26
+
27
+ def test_vectordb_from_params(self) -> None:
28
+ db: VectorDB = s2.vector_db(database=type(self).dbname)
29
+ index = db.create_index(
30
+ name='test_index', dimension=3,
31
+ tags={'name': 'test_tag'},
32
+ )
33
+ assert index.name == 'test_index'
34
+ assert index.dimension == 3
35
+ assert index.tags == {'name': 'test_tag'}
36
+ assert db.has_index('test_index')
37
+
38
+ def test_vectordb_from_connection(self) -> None:
39
+ with s2.connect(database=type(self).dbname) as conn:
40
+ db: VectorDB = conn.vector_db
41
+ index = db.create_index(
42
+ name='test_index_1',
43
+ dimension=4, tags={'name': 'test_tag'},
44
+ )
45
+ assert index.name == 'test_index_1'
46
+ assert index.dimension == 4
47
+ assert index.tags == {'name': 'test_tag'}
48
+ assert db.has_index('test_index_1')
49
+
50
+ db2: VectorDB = conn.vector_db
51
+ assert db2.has_index('test_index_1')
@@ -0,0 +1,192 @@
1
+ from typing import Any
2
+ from typing import Callable
3
+ from typing import Dict
4
+ from typing import Optional
5
+
6
+ from vectorstore import AndFilter # noqa: F401
7
+ from vectorstore import DeletionProtection # noqa: F401
8
+ from vectorstore import EqFilter # noqa: F401
9
+ from vectorstore import ExactMatchFilter # noqa: F401
10
+ from vectorstore import FilterTypedDict # noqa: F401
11
+ from vectorstore import GteFilter # noqa: F401
12
+ from vectorstore import GtFilter # noqa: F401
13
+ from vectorstore import IndexInterface # noqa: F401
14
+ from vectorstore import IndexList # noqa: F401
15
+ from vectorstore import IndexModel # noqa: F401
16
+ from vectorstore import IndexStatsTypedDict # noqa: F401
17
+ from vectorstore import InFilter # noqa: F401
18
+ from vectorstore import LteFilter # noqa: F401
19
+ from vectorstore import LtFilter # noqa: F401
20
+ from vectorstore import MatchTypedDict # noqa: F401
21
+ from vectorstore import Metric # noqa: F401
22
+ from vectorstore import NamespaceStatsTypedDict # noqa: F401
23
+ from vectorstore import NeFilter # noqa: F401
24
+ from vectorstore import NinFilter # noqa: F401
25
+ from vectorstore import OrFilter # noqa: F401
26
+ from vectorstore import SimpleFilter # noqa: F401
27
+ from vectorstore import Vector # noqa: F401
28
+ from vectorstore import VectorDictMetadataValue # noqa: F401
29
+ from vectorstore import VectorMetadataTypedDict # noqa: F401
30
+ from vectorstore import VectorTuple # noqa: F401
31
+ from vectorstore import VectorTupleWithMetadata # noqa: F401
32
+
33
+
34
+ def vector_db(
35
+ host: Optional[str] = None, user: Optional[str] = None,
36
+ password: Optional[str] = None, port: Optional[int] = None,
37
+ database: Optional[str] = None, driver: Optional[str] = None,
38
+ pure_python: Optional[bool] = None, local_infile: Optional[bool] = None,
39
+ charset: Optional[str] = None,
40
+ ssl_key: Optional[str] = None, ssl_cert: Optional[str] = None,
41
+ ssl_ca: Optional[str] = None, ssl_disabled: Optional[bool] = None,
42
+ ssl_cipher: Optional[str] = None, ssl_verify_cert: Optional[bool] = None,
43
+ tls_sni_servername: Optional[str] = None,
44
+ ssl_verify_identity: Optional[bool] = None,
45
+ conv: Optional[Dict[int, Callable[..., Any]]] = None,
46
+ credential_type: Optional[str] = None,
47
+ autocommit: Optional[bool] = None,
48
+ results_type: Optional[str] = None,
49
+ buffered: Optional[bool] = None,
50
+ results_format: Optional[str] = None,
51
+ program_name: Optional[str] = None,
52
+ conn_attrs: Optional[Dict[str, str]] = {},
53
+ multi_statements: Optional[bool] = None,
54
+ client_found_rows: Optional[bool] = None,
55
+ connect_timeout: Optional[int] = None,
56
+ nan_as_null: Optional[bool] = None,
57
+ inf_as_null: Optional[bool] = None,
58
+ encoding_errors: Optional[str] = None,
59
+ track_env: Optional[bool] = None,
60
+ enable_extended_data_types: Optional[bool] = None,
61
+ vector_data_format: Optional[str] = None,
62
+ parse_json: Optional[bool] = None,
63
+ pool_size: Optional[int] = 5,
64
+ max_overflow: Optional[int] = 10,
65
+ timeout: Optional[float] = 30,
66
+ ) -> Any:
67
+ """
68
+ Return a vectorstore API connection.
69
+ Database should be specified in the URL or as a keyword.
70
+
71
+ Parameters
72
+ ----------
73
+ host : str, optional
74
+ Hostname, IP address, or URL that describes the connection.
75
+ The scheme or protocol defines which database connector to use.
76
+ By default, the ``mysql`` scheme is used. To connect to the
77
+ HTTP API, the scheme can be set to ``http`` or ``https``. The username,
78
+ password, host, and port are specified as in a standard URL. The path
79
+ indicates the database name. The overall form of the URL is:
80
+ ``scheme://user:password@host:port/db_name``. The scheme can
81
+ typically be left off (unless you are using the HTTP API):
82
+ ``user:password@host:port/db_name``.
83
+ user : str, optional
84
+ Database user name
85
+ password : str, optional
86
+ Database user password
87
+ port : int, optional
88
+ Database port. This defaults to 3306 for non-HTTP connections, 80
89
+ for HTTP connections, and 443 for HTTPS connections.
90
+ database : str, optional
91
+ Database name.
92
+ pure_python : bool, optional
93
+ Use the connector in pure Python mode
94
+ local_infile : bool, optional
95
+ Allow local file uploads
96
+ charset : str, optional
97
+ Character set for string values
98
+ ssl_key : str, optional
99
+ File containing SSL key
100
+ ssl_cert : str, optional
101
+ File containing SSL certificate
102
+ ssl_ca : str, optional
103
+ File containing SSL certificate authority
104
+ ssl_cipher : str, optional
105
+ Sets the SSL cipher list
106
+ ssl_disabled : bool, optional
107
+ Disable SSL usage
108
+ ssl_verify_cert : bool, optional
109
+ Verify the server's certificate. This is automatically enabled if
110
+ ``ssl_ca`` is also specified.
111
+ ssl_verify_identity : bool, optional
112
+ Verify the server's identity
113
+ conv : dict[int, Callable], optional
114
+ Dictionary of data conversion functions
115
+ credential_type : str, optional
116
+ Type of authentication to use: auth.PASSWORD, auth.JWT, or auth.BROWSER_SSO
117
+ autocommit : bool, optional
118
+ Enable autocommits
119
+ results_type : str, optional
120
+ The form of the query results: tuples, namedtuples, dicts,
121
+ numpy, polars, pandas, arrow
122
+ buffered : bool, optional
123
+ Should the entire query result be buffered in memory? This is the default
124
+ behavior which allows full cursor control of the result, but does consume
125
+ more memory.
126
+ results_format : str, optional
127
+ Deprecated. This option has been renamed to results_type.
128
+ program_name : str, optional
129
+ Name of the program
130
+ conn_attrs : dict, optional
131
+ Additional connection attributes for telemetry. Example:
132
+ {'program_version': "1.0.2", "_connector_name": "dbt connector"}
133
+ multi_statements: bool, optional
134
+ Should multiple statements be allowed within a single query?
135
+ connect_timeout : int, optional
136
+ The timeout for connecting to the database in seconds.
137
+ (default: 10, min: 1, max: 31536000)
138
+ nan_as_null : bool, optional
139
+ Should NaN values be treated as NULLs when used in parameter
140
+ substitutions including uploaded data?
141
+ inf_as_null : bool, optional
142
+ Should Inf values be treated as NULLs when used in parameter
143
+ substitutions including uploaded data?
144
+ encoding_errors : str, optional
145
+ The error handler name for value decoding errors
146
+ track_env : bool, optional
147
+ Should the connection track the SINGLESTOREDB_URL environment variable?
148
+ enable_extended_data_types : bool, optional
149
+ Should extended data types (BSON, vector) be enabled?
150
+ vector_data_format : str, optional
151
+ Format for vector types: json or binary
152
+ pool_size : int, optional
153
+ The number of connections to keep in the connection pool. Default is 5.
154
+ max_overflow : int, optional
155
+ The maximum number of connections to allow beyond the pool size.
156
+ Default is 10.
157
+ timeout : float, optional
158
+ The timeout for acquiring a connection from the pool in seconds.
159
+ Default is 30 seconds.
160
+
161
+ See Also
162
+ --------
163
+ :class:`Connection`
164
+
165
+ Returns
166
+ -------
167
+ :class:`VectorDB`
168
+
169
+ """
170
+ from vectorstore import VectorDB
171
+ return VectorDB(
172
+ host=host, user=user, password=password, port=port,
173
+ database=database, driver=driver, pure_python=pure_python,
174
+ local_infile=local_infile, charset=charset,
175
+ ssl_key=ssl_key, ssl_cert=ssl_cert, ssl_ca=ssl_ca,
176
+ ssl_disabled=ssl_disabled, ssl_cipher=ssl_cipher,
177
+ ssl_verify_cert=ssl_verify_cert,
178
+ tls_sni_servername=tls_sni_servername,
179
+ ssl_verify_identity=ssl_verify_identity, conv=conv,
180
+ credential_type=credential_type, autocommit=autocommit,
181
+ results_type=results_type, buffered=buffered,
182
+ results_format=results_format, program_name=program_name,
183
+ conn_attrs=conn_attrs, multi_statements=multi_statements,
184
+ client_found_rows=client_found_rows,
185
+ connect_timeout=connect_timeout, nan_as_null=nan_as_null,
186
+ inf_as_null=inf_as_null, encoding_errors=encoding_errors,
187
+ track_env=track_env,
188
+ enable_extended_data_types=enable_extended_data_types,
189
+ vector_data_format=vector_data_format,
190
+ parse_json=parse_json, pool_size=pool_size,
191
+ max_overflow=max_overflow, timeout=timeout,
192
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: singlestoredb
3
- Version: 1.13.0
3
+ Version: 1.14.0
4
4
  Summary: Interface to the SingleStoreDB database and workspace management APIs
5
5
  Home-page: https://github.com/singlestore-labs/singlestoredb-python
6
6
  Author: SingleStore
@@ -11,7 +11,7 @@ Classifier: License :: OSI Approved :: Apache Software License
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3 :: Only
13
13
  Classifier: Topic :: Database
14
- Requires-Python: >=3.8
14
+ Requires-Python: >=3.9
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
17
  Requires-Dist: PyJWT
@@ -19,6 +19,7 @@ Requires-Dist: build
19
19
  Requires-Dist: parsimonious
20
20
  Requires-Dist: requests
21
21
  Requires-Dist: setuptools
22
+ Requires-Dist: singlestore-vectorstore >=0.1.2
22
23
  Requires-Dist: sqlparams
23
24
  Requires-Dist: wheel
24
25
  Requires-Dist: tomli >=1.1.0 ; python_version < "3.11"
@@ -1,15 +1,17 @@
1
- _singlestoredb_accel.pyd,sha256=aqbF2vvkOuTQ_vaPUxWlhe5ViVXZKcGtnS1GqDKx_3w,62464
2
- singlestoredb/__init__.py,sha256=UlzgYgzVnuyLhmIBExo4I5JnKj1LuJlm6l8rB6qzmMQ,1712
1
+ _singlestoredb_accel.pyd,sha256=0WgZ4A3-2pU8ZtZ5AUnpQOuHTeORtweaAr1qNDSJ2XM,62464
2
+ singlestoredb/__init__.py,sha256=GNnvb4MNLXKVSKSIAj7TseHmVPIMY7O2Qy37yI3OwL0,2162
3
3
  singlestoredb/auth.py,sha256=RmYiH0Wlc2RXc4pTlRMysxtBI445ggCIwojWKC_eDLE,7844
4
4
  singlestoredb/config.py,sha256=t3aiWi1i3kT5VhEgXca0gwT6591YkZUed-wzvVEBMs0,13424
5
- singlestoredb/connection.py,sha256=Ty_idVYH50Qx-j8WXy7NeB-DYLAcpdjGYTrTHkKzG9U,47309
5
+ singlestoredb/connection.py,sha256=I2AP_0l7hNARfXiSuVW953CsGYn_rKbTg_NyWEiGHbY,47542
6
6
  singlestoredb/converters.py,sha256=6gN3_RzSbw0Aimd5cGgBNPNq1yiHb1a_NK8qC9DmOQ0,21636
7
7
  singlestoredb/exceptions.py,sha256=WCCJrNSsU-hD-621Jpd6bwmvGftQ7byXkk-XKXlaxpg,3354
8
8
  singlestoredb/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  singlestoredb/pytest.py,sha256=TH364xRCN7_QaN0oRQDHixrEcDx_ZBgu3bmY0tvKrYU,9357
10
10
  singlestoredb/types.py,sha256=Lv0BEQl6aSZBiAe0OSI07FEJhcHZ9HX45iT9NU_mxHQ,10334
11
- singlestoredb/ai/__init__.py,sha256=nT048t90xqjaNhz7KJ10KfSVW4RcZRoujyC6po6Nmb8,61
12
- singlestoredb/ai/embeddings.py,sha256=KVvQY3viyYWXDBobFpj0xqiGRijt36zcHHlPNAfFAxA,770
11
+ singlestoredb/vectorstore.py,sha256=4YvXml3PpOEOtUGO7gylucKG2Rny8Bx6L29kmhsFiCY,8600
12
+ singlestoredb/ai/__init__.py,sha256=5vlx0XpzxalMKySnVF7y40gfuCgaz7COUKqN4KfNKF8,116
13
+ singlestoredb/ai/chat.py,sha256=oDig8C8QdPEHL-JmmpdFvt_Ct7-K_D0pG_UJ00WCZ7Y,828
14
+ singlestoredb/ai/embeddings.py,sha256=2F6ALJ5Z0PKih3mt3DIFepABcC3u0lshtWu2OUXWZgg,842
13
15
  singlestoredb/alchemy/__init__.py,sha256=bUmCl1xUn2v36RMbXLIrvgKzZSqx71mp1ReUw9JeVA8,2613
14
16
  singlestoredb/apps/__init__.py,sha256=7l4d4hCtm1ykDNf7UBi3Qnqg9N0qPs5jbQ0Al5tS5aM,173
15
17
  singlestoredb/apps/_cloud_functions.py,sha256=DMRC-4z3Q52hsKb_WlolfNcYV-5XmQGiJWbbaUxFZ0s,2794
@@ -20,15 +22,15 @@ singlestoredb/apps/_process.py,sha256=eMiBO4piaRX1S6zdnMx0X0E4J7E1XrXndnVW0GRYq1
20
22
  singlestoredb/apps/_python_udfs.py,sha256=PW-Lai3dFINsNtqrLlyUafWgs1j86qGqaNZpUD9OxVI,2811
21
23
  singlestoredb/apps/_stdout_supress.py,sha256=QRV-IHQQMvWMeJfqORuVE2-Il6ohO2Ti4IokFoTCJWE,689
22
24
  singlestoredb/apps/_uvicorn_util.py,sha256=Petkmq5keBPfXZsHBrnZfY3O2rUHvb3Cw6o-BRz5MP0,994
23
- singlestoredb/functions/__init__.py,sha256=EGweEMoVfInBCFginYDbCUNlbd31iA1tBYoXGt3XFgw,297
25
+ singlestoredb/functions/__init__.py,sha256=KPBjRaiVipCQwTSsryHvBE_qrwy7Kj74lKnutqplcao,487
24
26
  singlestoredb/functions/decorator.py,sha256=Zw4mTSzpTxFTdqfrFzdt_8hFptg0PXcrB3TbUMNynyU,5614
25
27
  singlestoredb/functions/dtypes.py,sha256=7w_atIL5jAvDNtu6RDCvY440Y9U-p19_Nf7R5ki46Co,41607
26
28
  singlestoredb/functions/signature.py,sha256=K1WftlfVei2xmizCxHi91z7mK8vW5VJxJAM7FiCnpEY,43926
27
29
  singlestoredb/functions/typing.py,sha256=5AJG4nx-HKCeemNxL0qc1VunYPJ5lHRzpYAK_qMybNw,1380
28
- singlestoredb/functions/utils.py,sha256=amYpDI_VICq1P5-jcuPFOJz0oeZ_lU07Os0dclOc96s,9228
30
+ singlestoredb/functions/utils.py,sha256=lZPxdYfHxrSfxGWCoF0YZyakVy2iYlozJ1lPSaPKRlo,11190
29
31
  singlestoredb/functions/ext/__init__.py,sha256=5ppI8IZN_zOwoJFdu_Oq9ipxtyHw9n6OMVAa_s9T_yY,24
30
32
  singlestoredb/functions/ext/arrow.py,sha256=mQhwaMpvCH_dP92WIhP_j-stu272n4UAHsFUOBTgnq0,9436
31
- singlestoredb/functions/ext/asgi.py,sha256=dgVrVRRetU76jn5nIG5s5I0KRcDXPeVwlKzjHlNx5fs,52078
33
+ singlestoredb/functions/ext/asgi.py,sha256=vFX-7P7aVItK76AxBw-DjLGy0nDV9KzcJYyLsLRCsi0,53455
32
34
  singlestoredb/functions/ext/json.py,sha256=j9133xOpyuSqb8smBmi_bPvv6OYCbNfpbLbEicyGqmQ,10522
33
35
  singlestoredb/functions/ext/mmap.py,sha256=0BN9OyEONZ174qdZWe2m3Xykt3-QcxyLYBt2iCG772Q,14123
34
36
  singlestoredb/functions/ext/rowdat_1.py,sha256=UNMMUA8mb6iIRfJV2FsdA20Sw6s-LEdHQ_tC4K4g70Q,21836
@@ -56,9 +58,10 @@ singlestoredb/management/billing_usage.py,sha256=0UHFSPCrN0nyeGFFM-HXS3NP8pYmYo2
56
58
  singlestoredb/management/cluster.py,sha256=auBzNYIXvnI6rq3DNpPgJhwWoT6JsyZRikjpON23Pxg,14867
57
59
  singlestoredb/management/export.py,sha256=2dCvnTnkxVI-arX3_375DtWzHkI1YNK5zaFYdHKE4cs,5277
58
60
  singlestoredb/management/files.py,sha256=Z9GpS2EHf9atE8kJdz1vJtsiT80O6TV00MPhqyXfAAw,31579
61
+ singlestoredb/management/inference_api.py,sha256=9d9-7edoZ6JI3SPvStcVDOSHOY6l38V1MFpyskdLAZY,2684
59
62
  singlestoredb/management/job.py,sha256=Npfe1JLYJlggGBrXLniPKwKUKF1i3alvSY1SFtvauSs,25498
60
63
  singlestoredb/management/manager.py,sha256=iB4XcerOPNoFc04TN40vjosMrDhlE7HMUyHsseRgjBQ,9224
61
- singlestoredb/management/organization.py,sha256=JBsNC4R3boUKdYvyCZyfGoVMC1mD6SPuMI1UssBVoOM,5611
64
+ singlestoredb/management/organization.py,sha256=viFG8eLVOs-NeoL6zm8nypFRQ-oiRDD2Sk-bL2b6hvw,6095
62
65
  singlestoredb/management/region.py,sha256=oGoLLS88dE1GmY7GCc0BV7X3f7bWwKQyeXOVBFmK9Pk,1678
63
66
  singlestoredb/management/utils.py,sha256=RtFhdIIliQ6aulYs99fgAQ0FxL2LfV-5oPRd9s_bBok,13626
64
67
  singlestoredb/management/workspace.py,sha256=D9DzpeWU7xFjpj8bBYiXyasjVYVANeYjTzgkz2aKvJQ,57984
@@ -125,12 +128,13 @@ singlestoredb/tests/test_ext_func.py,sha256=LhuPz8o3UF7x2LNod5oZ1tlxeLvGDEUE5Fnz
125
128
  singlestoredb/tests/test_ext_func_data.py,sha256=9kn8BWmCjkbnP6hSbFhmhcdW4OmVT-GSvBTIzFBLEys,48796
126
129
  singlestoredb/tests/test_fusion.py,sha256=S0Jk2NrcOitqM98r5fosHGbZ1sCZ2uxar5t48v-uOD0,52045
127
130
  singlestoredb/tests/test_http.py,sha256=7hwXe61hlUes3nji0MTTZweo94tJAlJ-vA5ct9geXFQ,8868
128
- singlestoredb/tests/test_management.py,sha256=EJY-JDFNS83_pM0KKJlEHoRiEZWHxjK2XWtM0YAy63U,46462
131
+ singlestoredb/tests/test_management.py,sha256=bq75vQw_Uc6qrPk-lxoSbsz6p1AkF9hzQqaXRL6vgGY,46499
129
132
  singlestoredb/tests/test_plugin.py,sha256=P1nXLnTafaHkHN-6bVbGryxTu7OWJPU9SYFZ_WQUwq8,845
130
133
  singlestoredb/tests/test_results.py,sha256=Zg1ynZFRZqalAMfNLOU5C6BDXaox6JxrKm_XZwVNFcg,6753
131
134
  singlestoredb/tests/test_types.py,sha256=YeVE6KPqlqzJke-4hbRmc8ko1E7RLHu5S8qLg04Bl5Y,4632
132
135
  singlestoredb/tests/test_udf.py,sha256=b1zOJVuhHvL_cMHYu5iJ5Cinu8gb2Rq_aaCUTaFlNZA,29553
133
136
  singlestoredb/tests/test_udf_returns.py,sha256=lDx26AUKGS4V0Vxf5ePO-VcrcX0QamyWGo-tm1GNc-E,16000
137
+ singlestoredb/tests/test_vectorstore.py,sha256=Zy9N63KPcm9bdjMN2dc1iwBZ5J8wK-p96xT6tF8Wk0M,1605
134
138
  singlestoredb/tests/test_xdict.py,sha256=5ArRJqd5aNXkPK7Y6sFeRbqZ59MZ1YaGBpSlDAbBrjM,10741
135
139
  singlestoredb/tests/utils.py,sha256=WR8GFNiC0lU4tz21Y3rlbbp9Gz9WcSwp2jpUSCj7RFU,5136
136
140
  singlestoredb/tests/ext_funcs/__init__.py,sha256=8kGNrG2qZVcmaAc4KAatrqZYPjBXtKbOqoG7zAwMtM4,14727
@@ -145,9 +149,9 @@ singlestoredb/utils/results.py,sha256=wR70LhCqlobniZf52r67zYLBOKjWHQm68NAskdRQND
145
149
  singlestoredb/utils/xdict.py,sha256=-wi1lSPTnY99fhVMBhPKJ8cCsQhNG4GMUfkEBDKYgCw,13321
146
150
  sqlx/__init__.py,sha256=4Sdn8HN-Hf8v0_wCt60DCckCg8BvgM3-9r4YVfZycRE,89
147
151
  sqlx/magic.py,sha256=6VBlotgjautjev599tHaTYOfcfOA9m6gV_-P1_Qc4lI,3622
148
- singlestoredb-1.13.0.dist-info/LICENSE,sha256=Bojenzui8aPNjlF3w4ojguDP7sTf8vFV_9Gc2UAG1sg,11542
149
- singlestoredb-1.13.0.dist-info/METADATA,sha256=ppKX6bSCclxe-ewTbeVSescf2Ngg1ZBmPvB5INV9QGE,5847
150
- singlestoredb-1.13.0.dist-info/WHEEL,sha256=c4k7z5HB0t-y0nBCv6KyJ6KCjn8SEGPddD0lhaPtU3E,96
151
- singlestoredb-1.13.0.dist-info/entry_points.txt,sha256=bSLaTWB5zGjpVYPAaI46MkkDup0su-eb3uAhCNYuRV0,48
152
- singlestoredb-1.13.0.dist-info/top_level.txt,sha256=lA65Vf4qAMfg_s1oG3LEO90h4t1Z-SPDbRqkevI3bSY,40
153
- singlestoredb-1.13.0.dist-info/RECORD,,
152
+ singlestoredb-1.14.0.dist-info/LICENSE,sha256=Bojenzui8aPNjlF3w4ojguDP7sTf8vFV_9Gc2UAG1sg,11542
153
+ singlestoredb-1.14.0.dist-info/METADATA,sha256=oAx3-B1zWSeqAjatJUyu_u1GzqOmZ9aYNKU0v0Mz8Ic,5895
154
+ singlestoredb-1.14.0.dist-info/WHEEL,sha256=c4k7z5HB0t-y0nBCv6KyJ6KCjn8SEGPddD0lhaPtU3E,96
155
+ singlestoredb-1.14.0.dist-info/entry_points.txt,sha256=bSLaTWB5zGjpVYPAaI46MkkDup0su-eb3uAhCNYuRV0,48
156
+ singlestoredb-1.14.0.dist-info/top_level.txt,sha256=lA65Vf4qAMfg_s1oG3LEO90h4t1Z-SPDbRqkevI3bSY,40
157
+ singlestoredb-1.14.0.dist-info/RECORD,,