pixeltable 0.4.18__py3-none-any.whl → 0.4.19__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 pixeltable might be problematic. Click here for more details.
- pixeltable/__init__.py +1 -1
- pixeltable/_version.py +1 -0
- pixeltable/catalog/catalog.py +119 -100
- pixeltable/catalog/column.py +104 -115
- pixeltable/catalog/globals.py +1 -2
- pixeltable/catalog/insertable_table.py +44 -49
- pixeltable/catalog/path.py +3 -4
- pixeltable/catalog/schema_object.py +4 -4
- pixeltable/catalog/table.py +118 -122
- pixeltable/catalog/table_metadata.py +6 -6
- pixeltable/catalog/table_version.py +322 -257
- pixeltable/catalog/table_version_handle.py +4 -4
- pixeltable/catalog/table_version_path.py +9 -10
- pixeltable/catalog/tbl_ops.py +9 -3
- pixeltable/catalog/view.py +34 -28
- pixeltable/config.py +14 -10
- pixeltable/dataframe.py +68 -77
- pixeltable/env.py +74 -64
- pixeltable/exec/aggregation_node.py +6 -6
- pixeltable/exec/cache_prefetch_node.py +10 -10
- pixeltable/exec/data_row_batch.py +3 -3
- pixeltable/exec/exec_context.py +4 -5
- pixeltable/exec/exec_node.py +5 -5
- pixeltable/exec/expr_eval/evaluators.py +6 -6
- pixeltable/exec/expr_eval/expr_eval_node.py +8 -7
- pixeltable/exec/expr_eval/globals.py +6 -6
- pixeltable/exec/expr_eval/row_buffer.py +1 -2
- pixeltable/exec/expr_eval/schedulers.py +11 -11
- pixeltable/exec/in_memory_data_node.py +2 -2
- pixeltable/exec/object_store_save_node.py +14 -17
- pixeltable/exec/sql_node.py +25 -25
- pixeltable/exprs/arithmetic_expr.py +4 -4
- pixeltable/exprs/array_slice.py +2 -2
- pixeltable/exprs/column_property_ref.py +3 -3
- pixeltable/exprs/column_ref.py +61 -74
- pixeltable/exprs/comparison.py +5 -5
- pixeltable/exprs/compound_predicate.py +3 -3
- pixeltable/exprs/data_row.py +12 -12
- pixeltable/exprs/expr.py +41 -31
- pixeltable/exprs/expr_dict.py +3 -3
- pixeltable/exprs/expr_set.py +3 -3
- pixeltable/exprs/function_call.py +14 -14
- pixeltable/exprs/in_predicate.py +4 -4
- pixeltable/exprs/inline_expr.py +8 -8
- pixeltable/exprs/is_null.py +1 -3
- pixeltable/exprs/json_mapper.py +8 -8
- pixeltable/exprs/json_path.py +6 -6
- pixeltable/exprs/literal.py +5 -5
- pixeltable/exprs/method_ref.py +2 -2
- pixeltable/exprs/object_ref.py +2 -2
- pixeltable/exprs/row_builder.py +14 -14
- pixeltable/exprs/rowid_ref.py +8 -8
- pixeltable/exprs/similarity_expr.py +50 -25
- pixeltable/exprs/sql_element_cache.py +4 -4
- pixeltable/exprs/string_op.py +2 -2
- pixeltable/exprs/type_cast.py +3 -5
- pixeltable/func/aggregate_function.py +8 -8
- pixeltable/func/callable_function.py +9 -9
- pixeltable/func/expr_template_function.py +3 -3
- pixeltable/func/function.py +15 -17
- pixeltable/func/function_registry.py +6 -7
- pixeltable/func/globals.py +2 -3
- pixeltable/func/mcp.py +2 -2
- pixeltable/func/query_template_function.py +16 -16
- pixeltable/func/signature.py +14 -14
- pixeltable/func/tools.py +11 -11
- pixeltable/func/udf.py +16 -18
- pixeltable/functions/__init__.py +1 -0
- pixeltable/functions/anthropic.py +7 -7
- pixeltable/functions/audio.py +76 -0
- pixeltable/functions/bedrock.py +6 -6
- pixeltable/functions/deepseek.py +4 -4
- pixeltable/functions/fireworks.py +2 -2
- pixeltable/functions/gemini.py +6 -6
- pixeltable/functions/globals.py +12 -12
- pixeltable/functions/groq.py +4 -4
- pixeltable/functions/huggingface.py +18 -20
- pixeltable/functions/image.py +7 -10
- pixeltable/functions/llama_cpp.py +7 -7
- pixeltable/functions/math.py +2 -3
- pixeltable/functions/mistralai.py +3 -3
- pixeltable/functions/ollama.py +9 -9
- pixeltable/functions/openai.py +21 -21
- pixeltable/functions/openrouter.py +7 -7
- pixeltable/functions/string.py +21 -28
- pixeltable/functions/timestamp.py +7 -8
- pixeltable/functions/together.py +4 -6
- pixeltable/functions/twelvelabs.py +92 -0
- pixeltable/functions/video.py +2 -24
- pixeltable/functions/vision.py +6 -6
- pixeltable/functions/whisper.py +7 -7
- pixeltable/functions/whisperx.py +16 -16
- pixeltable/globals.py +52 -36
- pixeltable/index/base.py +12 -8
- pixeltable/index/btree.py +19 -22
- pixeltable/index/embedding_index.py +30 -39
- pixeltable/io/datarows.py +3 -3
- pixeltable/io/external_store.py +13 -16
- pixeltable/io/fiftyone.py +5 -5
- pixeltable/io/globals.py +5 -5
- pixeltable/io/hf_datasets.py +4 -4
- pixeltable/io/label_studio.py +12 -12
- pixeltable/io/pandas.py +6 -6
- pixeltable/io/parquet.py +2 -2
- pixeltable/io/table_data_conduit.py +12 -12
- pixeltable/io/utils.py +2 -2
- pixeltable/iterators/audio.py +2 -2
- pixeltable/iterators/video.py +8 -13
- pixeltable/metadata/converters/convert_18.py +2 -2
- pixeltable/metadata/converters/convert_19.py +2 -2
- pixeltable/metadata/converters/convert_20.py +2 -2
- pixeltable/metadata/converters/convert_21.py +2 -2
- pixeltable/metadata/converters/convert_22.py +2 -2
- pixeltable/metadata/converters/convert_24.py +2 -2
- pixeltable/metadata/converters/convert_25.py +2 -2
- pixeltable/metadata/converters/convert_26.py +2 -2
- pixeltable/metadata/converters/convert_29.py +4 -4
- pixeltable/metadata/converters/convert_34.py +2 -2
- pixeltable/metadata/converters/convert_36.py +2 -2
- pixeltable/metadata/converters/convert_38.py +2 -2
- pixeltable/metadata/converters/convert_39.py +1 -2
- pixeltable/metadata/converters/util.py +11 -13
- pixeltable/metadata/schema.py +22 -21
- pixeltable/metadata/utils.py +2 -6
- pixeltable/mypy/mypy_plugin.py +5 -5
- pixeltable/plan.py +30 -28
- pixeltable/share/packager.py +7 -7
- pixeltable/share/publish.py +3 -3
- pixeltable/store.py +125 -61
- pixeltable/type_system.py +43 -46
- pixeltable/utils/__init__.py +1 -2
- pixeltable/utils/arrow.py +4 -4
- pixeltable/utils/av.py +8 -0
- pixeltable/utils/azure_store.py +305 -0
- pixeltable/utils/code.py +1 -2
- pixeltable/utils/dbms.py +15 -19
- pixeltable/utils/description_helper.py +2 -3
- pixeltable/utils/documents.py +5 -6
- pixeltable/utils/exception_handler.py +2 -2
- pixeltable/utils/filecache.py +5 -5
- pixeltable/utils/formatter.py +4 -6
- pixeltable/utils/gcs_store.py +9 -9
- pixeltable/utils/local_store.py +17 -17
- pixeltable/utils/object_stores.py +59 -43
- pixeltable/utils/s3_store.py +35 -30
- {pixeltable-0.4.18.dist-info → pixeltable-0.4.19.dist-info}/METADATA +1 -1
- pixeltable-0.4.19.dist-info/RECORD +213 -0
- pixeltable/__version__.py +0 -3
- pixeltable-0.4.18.dist-info/RECORD +0 -211
- {pixeltable-0.4.18.dist-info → pixeltable-0.4.19.dist-info}/WHEEL +0 -0
- {pixeltable-0.4.18.dist-info → pixeltable-0.4.19.dist-info}/entry_points.txt +0 -0
- {pixeltable-0.4.18.dist-info → pixeltable-0.4.19.dist-info}/licenses/LICENSE +0 -0
pixeltable/func/signature.py
CHANGED
|
@@ -4,7 +4,7 @@ import dataclasses
|
|
|
4
4
|
import inspect
|
|
5
5
|
import logging
|
|
6
6
|
import typing
|
|
7
|
-
from typing import TYPE_CHECKING, Any, Callable, ClassVar
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Callable, ClassVar
|
|
8
8
|
|
|
9
9
|
import pixeltable.exceptions as excs
|
|
10
10
|
import pixeltable.type_system as ts
|
|
@@ -18,11 +18,11 @@ _logger = logging.getLogger('pixeltable')
|
|
|
18
18
|
@dataclasses.dataclass
|
|
19
19
|
class Parameter:
|
|
20
20
|
name: str
|
|
21
|
-
col_type:
|
|
21
|
+
col_type: ts.ColumnType | None # None for variable parameters
|
|
22
22
|
kind: inspect._ParameterKind
|
|
23
23
|
# for some reason, this needs to precede is_batched in the dataclass definition,
|
|
24
24
|
# otherwise Python complains that an argument with a default is followed by an argument without a default
|
|
25
|
-
default:
|
|
25
|
+
default: 'exprs.Literal' | None = None # default value for the parameter
|
|
26
26
|
is_batched: bool = False # True if the parameter is a batched parameter (eg, Batch[dict])
|
|
27
27
|
|
|
28
28
|
def __post_init__(self) -> None:
|
|
@@ -104,7 +104,7 @@ class Signature:
|
|
|
104
104
|
return_type: ts.ColumnType,
|
|
105
105
|
parameters: list[Parameter],
|
|
106
106
|
is_batched: bool = False,
|
|
107
|
-
system_parameters:
|
|
107
|
+
system_parameters: list[str] | None = None,
|
|
108
108
|
):
|
|
109
109
|
assert isinstance(return_type, ts.ColumnType)
|
|
110
110
|
self.return_type = return_type
|
|
@@ -172,7 +172,7 @@ class Signature:
|
|
|
172
172
|
|
|
173
173
|
return True
|
|
174
174
|
|
|
175
|
-
def validate_args(self, bound_args: dict[str,
|
|
175
|
+
def validate_args(self, bound_args: dict[str, 'exprs.Expr' | None], context: str = '') -> None:
|
|
176
176
|
if context:
|
|
177
177
|
context = f' ({context})'
|
|
178
178
|
|
|
@@ -231,11 +231,11 @@ class Signature:
|
|
|
231
231
|
return f'({", ".join(param_strs)}) -> {self.get_return_type()}'
|
|
232
232
|
|
|
233
233
|
@classmethod
|
|
234
|
-
def _infer_type(cls, annotation:
|
|
234
|
+
def _infer_type(cls, annotation: type | None) -> tuple[ts.ColumnType | None, bool | None]:
|
|
235
235
|
"""Returns: (column type, is_batched) or (None, ...) if the type cannot be inferred"""
|
|
236
236
|
if annotation is None:
|
|
237
237
|
return (None, None)
|
|
238
|
-
py_type:
|
|
238
|
+
py_type: type | None = None
|
|
239
239
|
is_batched = False
|
|
240
240
|
if typing.get_origin(annotation) == typing.Annotated:
|
|
241
241
|
type_args = typing.get_args(annotation)
|
|
@@ -252,10 +252,10 @@ class Signature:
|
|
|
252
252
|
@classmethod
|
|
253
253
|
def create_parameters(
|
|
254
254
|
cls,
|
|
255
|
-
py_fn:
|
|
256
|
-
py_params:
|
|
257
|
-
param_types:
|
|
258
|
-
type_substitutions:
|
|
255
|
+
py_fn: Callable | None = None,
|
|
256
|
+
py_params: list[inspect.Parameter] | None = None,
|
|
257
|
+
param_types: list[ts.ColumnType] | None = None,
|
|
258
|
+
type_substitutions: dict | None = None,
|
|
259
259
|
is_cls_method: bool = False,
|
|
260
260
|
) -> list[Parameter]:
|
|
261
261
|
"""Ignores parameters starting with '_'."""
|
|
@@ -310,9 +310,9 @@ class Signature:
|
|
|
310
310
|
def create(
|
|
311
311
|
cls,
|
|
312
312
|
py_fn: Callable,
|
|
313
|
-
param_types:
|
|
314
|
-
return_type:
|
|
315
|
-
type_substitutions:
|
|
313
|
+
param_types: list[ts.ColumnType] | None = None,
|
|
314
|
+
return_type: ts.ColumnType | None = None,
|
|
315
|
+
type_substitutions: dict | None = None,
|
|
316
316
|
is_cls_method: bool = False,
|
|
317
317
|
) -> Signature:
|
|
318
318
|
"""Create a signature for the given Callable.
|
pixeltable/func/tools.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
-
from typing import TYPE_CHECKING, Any, Callable,
|
|
2
|
+
from typing import TYPE_CHECKING, Any, Callable, TypeVar
|
|
3
3
|
|
|
4
4
|
import pydantic
|
|
5
5
|
|
|
@@ -29,8 +29,8 @@ class Tool(pydantic.BaseModel):
|
|
|
29
29
|
model_config = pydantic.ConfigDict(arbitrary_types_allowed=True)
|
|
30
30
|
|
|
31
31
|
fn: Function
|
|
32
|
-
name:
|
|
33
|
-
description:
|
|
32
|
+
name: str | None = None
|
|
33
|
+
description: str | None = None
|
|
34
34
|
|
|
35
35
|
@property
|
|
36
36
|
def parameters(self) -> dict[str, Parameter]:
|
|
@@ -78,7 +78,7 @@ class Tool(pydantic.BaseModel):
|
|
|
78
78
|
class ToolChoice(pydantic.BaseModel):
|
|
79
79
|
auto: bool
|
|
80
80
|
required: bool
|
|
81
|
-
tool:
|
|
81
|
+
tool: str | None
|
|
82
82
|
parallel_tool_calls: bool
|
|
83
83
|
|
|
84
84
|
|
|
@@ -105,7 +105,7 @@ class Tools(pydantic.BaseModel):
|
|
|
105
105
|
) -> ToolChoice:
|
|
106
106
|
if sum([auto, required, tool is not None]) != 1:
|
|
107
107
|
raise excs.Error('Exactly one of `auto`, `required`, or `tool` must be specified.')
|
|
108
|
-
tool_name:
|
|
108
|
+
tool_name: str | None = None
|
|
109
109
|
if tool is not None:
|
|
110
110
|
try:
|
|
111
111
|
tool_obj = next(
|
|
@@ -121,27 +121,27 @@ class Tools(pydantic.BaseModel):
|
|
|
121
121
|
|
|
122
122
|
|
|
123
123
|
@udf
|
|
124
|
-
def _extract_str_tool_arg(kwargs: dict[str, Any], param_name: str) ->
|
|
124
|
+
def _extract_str_tool_arg(kwargs: dict[str, Any], param_name: str) -> str | None:
|
|
125
125
|
return _extract_arg(str, kwargs, param_name)
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
@udf
|
|
129
|
-
def _extract_int_tool_arg(kwargs: dict[str, Any], param_name: str) ->
|
|
129
|
+
def _extract_int_tool_arg(kwargs: dict[str, Any], param_name: str) -> int | None:
|
|
130
130
|
return _extract_arg(int, kwargs, param_name)
|
|
131
131
|
|
|
132
132
|
|
|
133
133
|
@udf
|
|
134
|
-
def _extract_float_tool_arg(kwargs: dict[str, Any], param_name: str) ->
|
|
134
|
+
def _extract_float_tool_arg(kwargs: dict[str, Any], param_name: str) -> float | None:
|
|
135
135
|
return _extract_arg(float, kwargs, param_name)
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
@udf
|
|
139
|
-
def _extract_bool_tool_arg(kwargs: dict[str, Any], param_name: str) ->
|
|
139
|
+
def _extract_bool_tool_arg(kwargs: dict[str, Any], param_name: str) -> bool | None:
|
|
140
140
|
return _extract_arg(bool, kwargs, param_name)
|
|
141
141
|
|
|
142
142
|
|
|
143
143
|
@udf
|
|
144
|
-
def _extract_json_tool_arg(kwargs: dict[str, Any], param_name: str) ->
|
|
144
|
+
def _extract_json_tool_arg(kwargs: dict[str, Any], param_name: str) -> ts.Json | None:
|
|
145
145
|
if param_name in kwargs:
|
|
146
146
|
return json.loads(kwargs[param_name])
|
|
147
147
|
return None
|
|
@@ -150,7 +150,7 @@ def _extract_json_tool_arg(kwargs: dict[str, Any], param_name: str) -> Optional[
|
|
|
150
150
|
T = TypeVar('T')
|
|
151
151
|
|
|
152
152
|
|
|
153
|
-
def _extract_arg(eval_fn: Callable[[Any], T], kwargs: dict[str, Any], param_name: str) ->
|
|
153
|
+
def _extract_arg(eval_fn: Callable[[Any], T], kwargs: dict[str, Any], param_name: str) -> T | None:
|
|
154
154
|
if param_name in kwargs:
|
|
155
155
|
return eval_fn(kwargs[param_name])
|
|
156
156
|
return None
|
pixeltable/func/udf.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import inspect
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Callable,
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Callable, Sequence, overload
|
|
5
5
|
|
|
6
6
|
import pixeltable.exceptions as excs
|
|
7
7
|
import pixeltable.type_system as ts
|
|
@@ -26,12 +26,12 @@ def udf(decorated_fn: Callable) -> CallableFunction: ...
|
|
|
26
26
|
@overload
|
|
27
27
|
def udf(
|
|
28
28
|
*,
|
|
29
|
-
batch_size:
|
|
30
|
-
substitute_fn:
|
|
29
|
+
batch_size: int | None = None,
|
|
30
|
+
substitute_fn: Callable | None = None,
|
|
31
31
|
is_method: bool = False,
|
|
32
32
|
is_property: bool = False,
|
|
33
|
-
resource_pool:
|
|
34
|
-
type_substitutions:
|
|
33
|
+
resource_pool: str | None = None,
|
|
34
|
+
type_substitutions: Sequence[dict] | None = None,
|
|
35
35
|
_force_stored: bool = False,
|
|
36
36
|
) -> Callable[[Callable], CallableFunction]: ...
|
|
37
37
|
|
|
@@ -39,7 +39,7 @@ def udf(
|
|
|
39
39
|
# pxt.udf() called explicitly on a Table:
|
|
40
40
|
@overload
|
|
41
41
|
def udf(
|
|
42
|
-
table: catalog.Table, /, *, return_value: Any = None, description:
|
|
42
|
+
table: catalog.Table, /, *, return_value: Any = None, description: str | None = None
|
|
43
43
|
) -> ExprTemplateFunction: ...
|
|
44
44
|
|
|
45
45
|
|
|
@@ -96,15 +96,15 @@ def udf(*args, **kwargs): # type: ignore[no-untyped-def]
|
|
|
96
96
|
|
|
97
97
|
def make_function(
|
|
98
98
|
decorated_fn: Callable,
|
|
99
|
-
return_type:
|
|
100
|
-
param_types:
|
|
101
|
-
batch_size:
|
|
102
|
-
substitute_fn:
|
|
99
|
+
return_type: ts.ColumnType | None = None,
|
|
100
|
+
param_types: list[ts.ColumnType] | None = None,
|
|
101
|
+
batch_size: int | None = None,
|
|
102
|
+
substitute_fn: Callable | None = None,
|
|
103
103
|
is_method: bool = False,
|
|
104
104
|
is_property: bool = False,
|
|
105
|
-
resource_pool:
|
|
106
|
-
type_substitutions:
|
|
107
|
-
function_name:
|
|
105
|
+
resource_pool: str | None = None,
|
|
106
|
+
type_substitutions: Sequence[dict] | None = None,
|
|
107
|
+
function_name: str | None = None,
|
|
108
108
|
force_stored: bool = False,
|
|
109
109
|
) -> CallableFunction:
|
|
110
110
|
"""
|
|
@@ -201,11 +201,11 @@ def expr_udf(py_fn: Callable) -> ExprTemplateFunction: ...
|
|
|
201
201
|
|
|
202
202
|
|
|
203
203
|
@overload
|
|
204
|
-
def expr_udf(*, param_types:
|
|
204
|
+
def expr_udf(*, param_types: list[ts.ColumnType] | None = None) -> Callable[[Callable], ExprTemplateFunction]: ...
|
|
205
205
|
|
|
206
206
|
|
|
207
207
|
def expr_udf(*args: Any, **kwargs: Any) -> Any:
|
|
208
|
-
def make_expr_template(py_fn: Callable, param_types:
|
|
208
|
+
def make_expr_template(py_fn: Callable, param_types: list[ts.ColumnType] | None) -> ExprTemplateFunction:
|
|
209
209
|
from pixeltable import exprs
|
|
210
210
|
|
|
211
211
|
if py_fn.__module__ != '__main__' and py_fn.__name__.isidentifier():
|
|
@@ -237,9 +237,7 @@ def expr_udf(*args: Any, **kwargs: Any) -> Any:
|
|
|
237
237
|
return lambda py_fn: make_expr_template(py_fn, kwargs['param_types'])
|
|
238
238
|
|
|
239
239
|
|
|
240
|
-
def from_table(
|
|
241
|
-
tbl: catalog.Table, return_value: Optional['exprs.Expr'], description: Optional[str]
|
|
242
|
-
) -> ExprTemplateFunction:
|
|
240
|
+
def from_table(tbl: catalog.Table, return_value: 'exprs.Expr' | None, description: str | None) -> ExprTemplateFunction:
|
|
243
241
|
"""
|
|
244
242
|
Constructs an `ExprTemplateFunction` from a `Table`.
|
|
245
243
|
|
pixeltable/functions/__init__.py
CHANGED
|
@@ -8,7 +8,7 @@ the [Working with Anthropic](https://pixeltable.readme.io/docs/working-with-anth
|
|
|
8
8
|
import datetime
|
|
9
9
|
import json
|
|
10
10
|
import logging
|
|
11
|
-
from typing import TYPE_CHECKING, Any, Iterable,
|
|
11
|
+
from typing import TYPE_CHECKING, Any, Iterable, cast
|
|
12
12
|
|
|
13
13
|
import httpx
|
|
14
14
|
|
|
@@ -130,7 +130,7 @@ class AnthropicRateLimitsInfo(env.RateLimitsInfo):
|
|
|
130
130
|
if retry_after_str is not None:
|
|
131
131
|
_logger.debug(f'retry-after: {retry_after_str}')
|
|
132
132
|
|
|
133
|
-
def get_retry_delay(self, exc: Exception) ->
|
|
133
|
+
def get_retry_delay(self, exc: Exception) -> float | None:
|
|
134
134
|
import anthropic
|
|
135
135
|
|
|
136
136
|
# deal with timeouts separately, they don't come with headers
|
|
@@ -152,10 +152,10 @@ async def messages(
|
|
|
152
152
|
*,
|
|
153
153
|
model: str,
|
|
154
154
|
max_tokens: int,
|
|
155
|
-
model_kwargs:
|
|
156
|
-
tools:
|
|
157
|
-
tool_choice:
|
|
158
|
-
_runtime_ctx:
|
|
155
|
+
model_kwargs: dict[str, Any] | None = None,
|
|
156
|
+
tools: list[dict[str, Any]] | None = None,
|
|
157
|
+
tool_choice: dict[str, Any] | None = None,
|
|
158
|
+
_runtime_ctx: env.RuntimeCtx | None = None,
|
|
159
159
|
) -> dict:
|
|
160
160
|
"""
|
|
161
161
|
Create a Message.
|
|
@@ -254,7 +254,7 @@ def invoke_tools(tools: Tools, response: exprs.Expr) -> exprs.InlineDict:
|
|
|
254
254
|
|
|
255
255
|
|
|
256
256
|
@pxt.udf
|
|
257
|
-
def _anthropic_response_to_pxt_tool_calls(response: dict) ->
|
|
257
|
+
def _anthropic_response_to_pxt_tool_calls(response: dict) -> dict | None:
|
|
258
258
|
anthropic_tool_calls = [r for r in response['content'] if r['type'] == 'tool_use']
|
|
259
259
|
if len(anthropic_tool_calls) == 0:
|
|
260
260
|
return None
|
pixeltable/functions/audio.py
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
Pixeltable [UDFs](https://pixeltable.readme.io/docs/user-defined-functions-udfs) for `AudioType`.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import av
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
5
8
|
import pixeltable as pxt
|
|
6
9
|
import pixeltable.utils.av as av_utils
|
|
7
10
|
from pixeltable.utils.code import local_public_names
|
|
11
|
+
from pixeltable.utils.local_store import TempStore
|
|
8
12
|
|
|
9
13
|
|
|
10
14
|
@pxt.udf(is_method=True)
|
|
@@ -51,6 +55,78 @@ def get_metadata(audio: pxt.Audio) -> dict:
|
|
|
51
55
|
return av_utils.get_metadata(audio)
|
|
52
56
|
|
|
53
57
|
|
|
58
|
+
@pxt.udf()
|
|
59
|
+
def encode_audio(
|
|
60
|
+
audio_data: pxt.Array[pxt.Float], *, input_sample_rate: int, format: str, output_sample_rate: int | None = None
|
|
61
|
+
) -> pxt.Audio:
|
|
62
|
+
"""
|
|
63
|
+
Encodes an audio clip represented as an array into a specified audio format.
|
|
64
|
+
|
|
65
|
+
Parameters:
|
|
66
|
+
audio_data: An array of sampled amplitudes. The accepted array shapes are `(N,)` or `(1, N)` for mono audio
|
|
67
|
+
or `(2, N)` for stereo.
|
|
68
|
+
input_sample_rate: The sample rate of the input audio data.
|
|
69
|
+
format: The desired output audio format. The supported formats are 'wav', 'mp3', 'flac', and 'mp4'.
|
|
70
|
+
output_sample_rate: The desired sample rate for the output audio. Defaults to the input sample rate if
|
|
71
|
+
unspecified.
|
|
72
|
+
|
|
73
|
+
Examples:
|
|
74
|
+
Add a computed column with encoded FLAC audio files to a table with audio data (as arrays of floats) and sample
|
|
75
|
+
rates:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
t.add_computed_column(
|
|
79
|
+
audio_file=encode_audio(
|
|
80
|
+
t.audio_data, input_sample_rate=t.sample_rate, format='flac'
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
```
|
|
84
|
+
"""
|
|
85
|
+
if format not in av_utils.AUDIO_FORMATS:
|
|
86
|
+
raise pxt.Error(f'Only the following formats are supported: {av_utils.AUDIO_FORMATS.keys()}')
|
|
87
|
+
if output_sample_rate is None:
|
|
88
|
+
output_sample_rate = input_sample_rate
|
|
89
|
+
|
|
90
|
+
codec, ext = av_utils.AUDIO_FORMATS[format]
|
|
91
|
+
output_path = str(TempStore.create_path(extension=f'.{ext}'))
|
|
92
|
+
|
|
93
|
+
match audio_data.shape:
|
|
94
|
+
case (_,):
|
|
95
|
+
# Mono audio as 1D array, reshape for pyav
|
|
96
|
+
layout = 'mono'
|
|
97
|
+
audio_data_transformed = audio_data[None, :]
|
|
98
|
+
case (1, _):
|
|
99
|
+
# Mono audio as 2D array, simply reshape and transpose the input for pyav
|
|
100
|
+
layout = 'mono'
|
|
101
|
+
audio_data_transformed = audio_data.reshape(-1, 1).transpose()
|
|
102
|
+
case (2, _):
|
|
103
|
+
# Stereo audio. Input layout: [[L0, L1, L2, ...],[R0, R1, R2, ...]],
|
|
104
|
+
# pyav expects: [L0, R0, L1, R1, L2, R2, ...]
|
|
105
|
+
layout = 'stereo'
|
|
106
|
+
audio_data_transformed = np.empty(audio_data.shape[1] * 2, dtype=audio_data.dtype)
|
|
107
|
+
audio_data_transformed[0::2] = audio_data[0]
|
|
108
|
+
audio_data_transformed[1::2] = audio_data[1]
|
|
109
|
+
audio_data_transformed = audio_data_transformed.reshape(1, -1)
|
|
110
|
+
case _:
|
|
111
|
+
raise pxt.Error(
|
|
112
|
+
f'Supported input array shapes are (N,), (1, N) for mono and (2, N) for stereo, got {audio_data.shape}'
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
with av.open(output_path, mode='w') as output_container:
|
|
116
|
+
stream = output_container.add_stream(codec, rate=output_sample_rate)
|
|
117
|
+
assert isinstance(stream, av.AudioStream)
|
|
118
|
+
|
|
119
|
+
frame = av.AudioFrame.from_ndarray(audio_data_transformed, format='flt', layout=layout)
|
|
120
|
+
frame.sample_rate = input_sample_rate
|
|
121
|
+
|
|
122
|
+
for packet in stream.encode(frame):
|
|
123
|
+
output_container.mux(packet)
|
|
124
|
+
for packet in stream.encode():
|
|
125
|
+
output_container.mux(packet)
|
|
126
|
+
|
|
127
|
+
return output_path
|
|
128
|
+
|
|
129
|
+
|
|
54
130
|
__all__ = local_public_names(__name__)
|
|
55
131
|
|
|
56
132
|
|
pixeltable/functions/bedrock.py
CHANGED
|
@@ -6,7 +6,7 @@ including Anthropic Claude, Amazon Titan, and other providers.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import logging
|
|
9
|
-
from typing import TYPE_CHECKING, Any
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
10
|
|
|
11
11
|
import pixeltable as pxt
|
|
12
12
|
from pixeltable import env, exprs
|
|
@@ -36,10 +36,10 @@ def converse(
|
|
|
36
36
|
messages: list[dict[str, Any]],
|
|
37
37
|
*,
|
|
38
38
|
model_id: str,
|
|
39
|
-
system:
|
|
40
|
-
inference_config:
|
|
41
|
-
additional_model_request_fields:
|
|
42
|
-
tool_config:
|
|
39
|
+
system: list[dict[str, Any]] | None = None,
|
|
40
|
+
inference_config: dict | None = None,
|
|
41
|
+
additional_model_request_fields: dict | None = None,
|
|
42
|
+
tool_config: list[dict] | None = None,
|
|
43
43
|
) -> dict:
|
|
44
44
|
"""
|
|
45
45
|
Generate a conversation response.
|
|
@@ -111,7 +111,7 @@ def invoke_tools(tools: Tools, response: exprs.Expr) -> exprs.InlineDict:
|
|
|
111
111
|
|
|
112
112
|
|
|
113
113
|
@pxt.udf
|
|
114
|
-
def _bedrock_response_to_pxt_tool_calls(response: dict) ->
|
|
114
|
+
def _bedrock_response_to_pxt_tool_calls(response: dict) -> dict | None:
|
|
115
115
|
if response.get('stopReason') != 'tool_use':
|
|
116
116
|
return None
|
|
117
117
|
|
pixeltable/functions/deepseek.py
CHANGED
|
@@ -6,7 +6,7 @@ and other AI capabilities.
|
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import json
|
|
9
|
-
from typing import TYPE_CHECKING, Any
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
10
|
|
|
11
11
|
import httpx
|
|
12
12
|
|
|
@@ -38,9 +38,9 @@ async def chat_completions(
|
|
|
38
38
|
messages: list,
|
|
39
39
|
*,
|
|
40
40
|
model: str,
|
|
41
|
-
model_kwargs:
|
|
42
|
-
tools:
|
|
43
|
-
tool_choice:
|
|
41
|
+
model_kwargs: dict[str, Any] | None = None,
|
|
42
|
+
tools: list[dict[str, Any]] | None = None,
|
|
43
|
+
tool_choice: dict[str, Any] | None = None,
|
|
44
44
|
) -> dict:
|
|
45
45
|
"""
|
|
46
46
|
Creates a model response for the given chat conversation.
|
|
@@ -5,7 +5,7 @@ first `pip install fireworks-ai` and configure your Fireworks AI credentials, as
|
|
|
5
5
|
the [Working with Fireworks](https://pixeltable.readme.io/docs/working-with-fireworks) tutorial.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from typing import TYPE_CHECKING, Any
|
|
8
|
+
from typing import TYPE_CHECKING, Any
|
|
9
9
|
|
|
10
10
|
import pixeltable as pxt
|
|
11
11
|
from pixeltable import env
|
|
@@ -29,7 +29,7 @@ def _fireworks_client() -> 'fireworks.client.Fireworks':
|
|
|
29
29
|
|
|
30
30
|
@pxt.udf(resource_pool='request-rate:fireworks')
|
|
31
31
|
async def chat_completions(
|
|
32
|
-
messages: list[dict[str, str]], *, model: str, model_kwargs:
|
|
32
|
+
messages: list[dict[str, str]], *, model: str, model_kwargs: dict[str, Any] | None = None
|
|
33
33
|
) -> dict:
|
|
34
34
|
"""
|
|
35
35
|
Creates a model response for the given chat conversation.
|
pixeltable/functions/gemini.py
CHANGED
|
@@ -8,7 +8,7 @@ the [Working with Gemini](https://pixeltable.readme.io/docs/working-with-gemini)
|
|
|
8
8
|
import asyncio
|
|
9
9
|
import io
|
|
10
10
|
from pathlib import Path
|
|
11
|
-
from typing import TYPE_CHECKING
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
12
|
|
|
13
13
|
import PIL.Image
|
|
14
14
|
|
|
@@ -34,7 +34,7 @@ def _genai_client() -> 'genai.client.Client':
|
|
|
34
34
|
|
|
35
35
|
@pxt.udf(resource_pool='request-rate:gemini')
|
|
36
36
|
async def generate_content(
|
|
37
|
-
contents: str, *, model: str, config:
|
|
37
|
+
contents: str, *, model: str, config: dict | None = None, tools: list[dict] | None = None
|
|
38
38
|
) -> dict:
|
|
39
39
|
"""
|
|
40
40
|
Generate content from the specified model. For additional details, see:
|
|
@@ -103,7 +103,7 @@ def invoke_tools(tools: pxt.func.Tools, response: exprs.Expr) -> exprs.InlineDic
|
|
|
103
103
|
|
|
104
104
|
|
|
105
105
|
@pxt.udf
|
|
106
|
-
def _gemini_response_to_pxt_tool_calls(response: dict) ->
|
|
106
|
+
def _gemini_response_to_pxt_tool_calls(response: dict) -> dict | None:
|
|
107
107
|
pxt_tool_calls: dict[str, list[dict]] = {}
|
|
108
108
|
for part in response['candidates'][0]['content']['parts']:
|
|
109
109
|
tool_call = part.get('function_call')
|
|
@@ -123,7 +123,7 @@ def _(model: str) -> str:
|
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
@pxt.udf(resource_pool='request-rate:imagen')
|
|
126
|
-
async def generate_images(prompt: str, *, model: str, config:
|
|
126
|
+
async def generate_images(prompt: str, *, model: str, config: dict | None = None) -> PIL.Image.Image:
|
|
127
127
|
"""
|
|
128
128
|
Generates images based on a text description and configuration. For additional details, see:
|
|
129
129
|
<https://ai.google.dev/gemini-api/docs/image-generation>
|
|
@@ -167,7 +167,7 @@ def _(model: str) -> str:
|
|
|
167
167
|
|
|
168
168
|
@pxt.udf(resource_pool='request-rate:veo')
|
|
169
169
|
async def generate_videos(
|
|
170
|
-
prompt:
|
|
170
|
+
prompt: str | None = None, image: PIL.Image.Image | None = None, *, model: str, config: dict | None = None
|
|
171
171
|
) -> pxt.Video:
|
|
172
172
|
"""
|
|
173
173
|
Generates videos based on a text description and configuration. For additional details, see:
|
|
@@ -205,7 +205,7 @@ async def generate_videos(
|
|
|
205
205
|
if prompt is None and image is None:
|
|
206
206
|
raise excs.Error('At least one of `prompt` or `image` must be provided.')
|
|
207
207
|
|
|
208
|
-
image_:
|
|
208
|
+
image_: types.Image | None = None
|
|
209
209
|
if image is not None:
|
|
210
210
|
with io.BytesIO() as buffer:
|
|
211
211
|
image.save(buffer, format='jpeg')
|
pixeltable/functions/globals.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import builtins
|
|
2
2
|
import typing
|
|
3
|
-
from typing import Any, Callable
|
|
3
|
+
from typing import Any, Callable
|
|
4
4
|
|
|
5
5
|
import sqlalchemy as sql
|
|
6
6
|
|
|
@@ -19,7 +19,7 @@ def cast(expr: exprs.Expr, target_type: ts.ColumnType | type | _GenericAlias) ->
|
|
|
19
19
|
T = typing.TypeVar('T')
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
@func.uda(allows_window=True, type_substitutions=({T:
|
|
22
|
+
@func.uda(allows_window=True, type_substitutions=({T: int | None}, {T: float | None})) # type: ignore[misc]
|
|
23
23
|
class sum(func.Aggregator, typing.Generic[T]):
|
|
24
24
|
"""Sums the selected integers or floats."""
|
|
25
25
|
|
|
@@ -39,7 +39,7 @@ class sum(func.Aggregator, typing.Generic[T]):
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
@sum.to_sql
|
|
42
|
-
def _(val: sql.ColumnElement) ->
|
|
42
|
+
def _(val: sql.ColumnElement) -> sql.ColumnElement | None:
|
|
43
43
|
# This can produce a Decimal. We are deliberately avoiding an explicit cast to a Bigint here, because that can
|
|
44
44
|
# cause overflows in Postgres. We're instead doing the conversion to the target type in SqlNode.__iter__().
|
|
45
45
|
return sql.sql.func.sum(val)
|
|
@@ -49,7 +49,7 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
|
|
|
49
49
|
allows_window=True,
|
|
50
50
|
# Allow counting non-null values of any type
|
|
51
51
|
# TODO: should we have an "Any" type that can be used here?
|
|
52
|
-
type_substitutions=tuple({T:
|
|
52
|
+
type_substitutions=tuple({T: t | None} for t in ts.ALL_PIXELTABLE_TYPES), # type: ignore[misc]
|
|
53
53
|
)
|
|
54
54
|
class count(func.Aggregator, typing.Generic[T]):
|
|
55
55
|
def __init__(self) -> None:
|
|
@@ -64,13 +64,13 @@ class count(func.Aggregator, typing.Generic[T]):
|
|
|
64
64
|
|
|
65
65
|
|
|
66
66
|
@count.to_sql
|
|
67
|
-
def _(val: sql.ColumnElement) ->
|
|
67
|
+
def _(val: sql.ColumnElement) -> sql.ColumnElement | None:
|
|
68
68
|
return sql.sql.func.count(val)
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
@func.uda(
|
|
72
72
|
allows_window=True,
|
|
73
|
-
type_substitutions=tuple({T:
|
|
73
|
+
type_substitutions=tuple({T: t | None} for t in (str, int, float, bool, ts.Timestamp)), # type: ignore[misc]
|
|
74
74
|
)
|
|
75
75
|
class min(func.Aggregator, typing.Generic[T]):
|
|
76
76
|
def __init__(self) -> None:
|
|
@@ -89,7 +89,7 @@ class min(func.Aggregator, typing.Generic[T]):
|
|
|
89
89
|
|
|
90
90
|
|
|
91
91
|
@min.to_sql
|
|
92
|
-
def _(val: sql.ColumnElement) ->
|
|
92
|
+
def _(val: sql.ColumnElement) -> sql.ColumnElement | None:
|
|
93
93
|
if val.type.python_type is bool:
|
|
94
94
|
# TODO: min/max aggregation of booleans is not supported in Postgres (but it is in Python).
|
|
95
95
|
# Right now we simply force the computation to be done in Python; we might consider implementing an alternate
|
|
@@ -100,7 +100,7 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
|
|
|
100
100
|
|
|
101
101
|
@func.uda(
|
|
102
102
|
allows_window=True,
|
|
103
|
-
type_substitutions=tuple({T:
|
|
103
|
+
type_substitutions=tuple({T: t | None} for t in (str, int, float, bool, ts.Timestamp)), # type: ignore[misc]
|
|
104
104
|
)
|
|
105
105
|
class max(func.Aggregator, typing.Generic[T]):
|
|
106
106
|
def __init__(self) -> None:
|
|
@@ -119,14 +119,14 @@ class max(func.Aggregator, typing.Generic[T]):
|
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
@max.to_sql
|
|
122
|
-
def _(val: sql.ColumnElement) ->
|
|
122
|
+
def _(val: sql.ColumnElement) -> sql.ColumnElement | None:
|
|
123
123
|
if val.type.python_type is bool:
|
|
124
124
|
# TODO: see comment in @min.to_sql.
|
|
125
125
|
return None
|
|
126
126
|
return sql.sql.func.max(val)
|
|
127
127
|
|
|
128
128
|
|
|
129
|
-
@func.uda(type_substitutions=({T:
|
|
129
|
+
@func.uda(type_substitutions=({T: int | None}, {T: float | None})) # type: ignore[misc]
|
|
130
130
|
class mean(func.Aggregator, typing.Generic[T]):
|
|
131
131
|
def __init__(self) -> None:
|
|
132
132
|
self.sum: T = None
|
|
@@ -141,14 +141,14 @@ class mean(func.Aggregator, typing.Generic[T]):
|
|
|
141
141
|
self.sum += val # type: ignore[operator]
|
|
142
142
|
self.count += 1
|
|
143
143
|
|
|
144
|
-
def value(self) ->
|
|
144
|
+
def value(self) -> float | None: # Always a float
|
|
145
145
|
if self.count == 0:
|
|
146
146
|
return None
|
|
147
147
|
return self.sum / self.count # type: ignore[operator]
|
|
148
148
|
|
|
149
149
|
|
|
150
150
|
@mean.to_sql
|
|
151
|
-
def _(val: sql.ColumnElement) ->
|
|
151
|
+
def _(val: sql.ColumnElement) -> sql.ColumnElement | None:
|
|
152
152
|
return sql.sql.func.avg(val)
|
|
153
153
|
|
|
154
154
|
|
pixeltable/functions/groq.py
CHANGED
|
@@ -5,7 +5,7 @@ first `pip install groq` and configure your Groq credentials, as described in
|
|
|
5
5
|
the [Working with Groq](https://pixeltable.readme.io/docs/working-with-groq) tutorial.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from typing import TYPE_CHECKING, Any
|
|
8
|
+
from typing import TYPE_CHECKING, Any
|
|
9
9
|
|
|
10
10
|
import pixeltable as pxt
|
|
11
11
|
from pixeltable import exprs
|
|
@@ -34,9 +34,9 @@ async def chat_completions(
|
|
|
34
34
|
messages: list[dict[str, str]],
|
|
35
35
|
*,
|
|
36
36
|
model: str,
|
|
37
|
-
model_kwargs:
|
|
38
|
-
tools:
|
|
39
|
-
tool_choice:
|
|
37
|
+
model_kwargs: dict[str, Any] | None = None,
|
|
38
|
+
tools: list[dict[str, Any]] | None = None,
|
|
39
|
+
tool_choice: dict[str, Any] | None = None,
|
|
40
40
|
) -> dict:
|
|
41
41
|
"""
|
|
42
42
|
Chat Completion API.
|