pixeltable 0.3.9__py3-none-any.whl → 0.3.11__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 +2 -3
- pixeltable/__version__.py +2 -2
- pixeltable/catalog/__init__.py +2 -1
- pixeltable/catalog/catalog.py +63 -36
- pixeltable/catalog/column.py +11 -4
- pixeltable/catalog/dir.py +5 -5
- pixeltable/catalog/globals.py +28 -14
- pixeltable/catalog/insertable_table.py +81 -43
- pixeltable/catalog/path.py +2 -2
- pixeltable/catalog/table.py +140 -109
- pixeltable/catalog/table_version.py +60 -43
- pixeltable/catalog/table_version_handle.py +3 -0
- pixeltable/catalog/table_version_path.py +1 -1
- pixeltable/catalog/view.py +17 -9
- pixeltable/dataframe.py +5 -3
- pixeltable/env.py +109 -43
- pixeltable/exec/__init__.py +2 -0
- pixeltable/exec/aggregation_node.py +6 -8
- pixeltable/exec/cache_prefetch_node.py +4 -7
- pixeltable/exec/component_iteration_node.py +1 -3
- pixeltable/exec/data_row_batch.py +1 -2
- pixeltable/exec/exec_context.py +1 -1
- pixeltable/exec/exec_node.py +2 -3
- pixeltable/exec/expr_eval/__init__.py +2 -0
- pixeltable/exec/expr_eval/evaluators.py +137 -20
- pixeltable/exec/expr_eval/expr_eval_node.py +43 -64
- pixeltable/exec/expr_eval/globals.py +68 -7
- pixeltable/exec/expr_eval/schedulers.py +25 -23
- pixeltable/exec/in_memory_data_node.py +8 -6
- pixeltable/exec/row_update_node.py +3 -4
- pixeltable/exec/sql_node.py +16 -17
- pixeltable/exprs/__init__.py +3 -2
- pixeltable/exprs/arithmetic_expr.py +2 -0
- pixeltable/exprs/column_property_ref.py +1 -1
- pixeltable/exprs/column_ref.py +39 -3
- pixeltable/exprs/compound_predicate.py +1 -1
- pixeltable/exprs/data_row.py +17 -1
- pixeltable/exprs/expr.py +51 -21
- pixeltable/exprs/function_call.py +34 -2
- pixeltable/exprs/globals.py +12 -0
- pixeltable/exprs/json_mapper.py +95 -48
- pixeltable/exprs/json_path.py +3 -10
- pixeltable/exprs/method_ref.py +2 -2
- pixeltable/exprs/object_ref.py +2 -2
- pixeltable/exprs/row_builder.py +33 -6
- pixeltable/exprs/similarity_expr.py +6 -21
- pixeltable/exprs/sql_element_cache.py +1 -1
- pixeltable/exprs/string_op.py +107 -0
- pixeltable/ext/__init__.py +1 -1
- pixeltable/ext/functions/__init__.py +1 -1
- pixeltable/ext/functions/whisperx.py +1 -1
- pixeltable/ext/functions/yolox.py +22 -65
- pixeltable/func/aggregate_function.py +1 -1
- pixeltable/func/callable_function.py +2 -5
- pixeltable/func/expr_template_function.py +22 -2
- pixeltable/func/function.py +4 -5
- pixeltable/func/function_registry.py +1 -1
- pixeltable/func/signature.py +1 -1
- pixeltable/func/tools.py +2 -2
- pixeltable/func/udf.py +2 -2
- pixeltable/functions/__init__.py +2 -2
- pixeltable/functions/anthropic.py +2 -2
- pixeltable/functions/audio.py +1 -1
- pixeltable/functions/deepseek.py +1 -1
- pixeltable/functions/fireworks.py +1 -1
- pixeltable/functions/globals.py +22 -11
- pixeltable/functions/huggingface.py +1 -1
- pixeltable/functions/image.py +1 -1
- pixeltable/functions/json.py +1 -1
- pixeltable/functions/llama_cpp.py +1 -1
- pixeltable/functions/math.py +1 -1
- pixeltable/functions/mistralai.py +1 -1
- pixeltable/functions/ollama.py +1 -1
- pixeltable/functions/openai.py +2 -2
- pixeltable/functions/replicate.py +1 -1
- pixeltable/functions/string.py +1 -1
- pixeltable/functions/timestamp.py +1 -1
- pixeltable/functions/together.py +1 -1
- pixeltable/functions/util.py +1 -1
- pixeltable/functions/video.py +2 -2
- pixeltable/functions/vision.py +2 -2
- pixeltable/globals.py +85 -33
- pixeltable/index/embedding_index.py +12 -1
- pixeltable/io/__init__.py +8 -5
- pixeltable/io/datarows.py +138 -0
- pixeltable/io/external_store.py +8 -5
- pixeltable/io/fiftyone.py +6 -7
- pixeltable/io/globals.py +7 -160
- pixeltable/io/hf_datasets.py +21 -98
- pixeltable/io/label_studio.py +21 -20
- pixeltable/io/pandas.py +35 -48
- pixeltable/io/parquet.py +17 -42
- pixeltable/io/table_data_conduit.py +569 -0
- pixeltable/io/utils.py +6 -21
- pixeltable/iterators/__init__.py +1 -1
- pixeltable/metadata/__init__.py +6 -4
- pixeltable/metadata/converters/convert_24.py +3 -3
- pixeltable/metadata/converters/convert_25.py +1 -1
- pixeltable/metadata/converters/convert_29.py +1 -1
- pixeltable/metadata/converters/convert_30.py +50 -0
- pixeltable/metadata/converters/util.py +26 -1
- pixeltable/metadata/notes.py +1 -0
- pixeltable/metadata/schema.py +3 -0
- pixeltable/store.py +2 -2
- pixeltable/type_system.py +19 -7
- pixeltable/utils/arrow.py +32 -7
- pixeltable/utils/console_output.py +3 -2
- pixeltable/utils/coroutine.py +3 -3
- pixeltable/utils/dbms.py +66 -0
- pixeltable/utils/documents.py +61 -67
- pixeltable/utils/filecache.py +1 -1
- pixeltable/utils/http_server.py +3 -2
- pixeltable/utils/pytorch.py +1 -1
- pixeltable/utils/sql.py +1 -1
- pixeltable-0.3.11.dist-info/METADATA +436 -0
- pixeltable-0.3.11.dist-info/RECORD +179 -0
- {pixeltable-0.3.9.dist-info → pixeltable-0.3.11.dist-info}/WHEEL +1 -1
- pixeltable/catalog/path_dict.py +0 -169
- pixeltable-0.3.9.dist-info/METADATA +0 -382
- pixeltable-0.3.9.dist-info/RECORD +0 -175
- {pixeltable-0.3.9.dist-info → pixeltable-0.3.11.dist-info}/LICENSE +0 -0
- {pixeltable-0.3.9.dist-info → pixeltable-0.3.11.dist-info}/entry_points.txt +0 -0
|
@@ -1,21 +1,15 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from
|
|
3
|
-
from typing import TYPE_CHECKING, Iterable, Iterator
|
|
4
|
-
from urllib.request import urlretrieve
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
5
3
|
|
|
6
|
-
import numpy as np
|
|
7
4
|
import PIL.Image
|
|
8
5
|
|
|
9
6
|
import pixeltable as pxt
|
|
10
|
-
from pixeltable import env
|
|
11
7
|
from pixeltable.func import Batch
|
|
12
8
|
from pixeltable.functions.util import normalize_image_mode
|
|
13
9
|
from pixeltable.utils.code import local_public_names
|
|
14
10
|
|
|
15
11
|
if TYPE_CHECKING:
|
|
16
|
-
import
|
|
17
|
-
from yolox.exp import Exp # type: ignore[import-untyped]
|
|
18
|
-
from yolox.models import YOLOX # type: ignore[import-untyped]
|
|
12
|
+
from yolox.models import Yolox, YoloxProcessor # type: ignore[import-untyped]
|
|
19
13
|
|
|
20
14
|
_logger = logging.getLogger('pixeltable')
|
|
21
15
|
|
|
@@ -30,7 +24,7 @@ def yolox(images: Batch[PIL.Image.Image], *, model_id: str, threshold: float = 0
|
|
|
30
24
|
|
|
31
25
|
__Requirements__:
|
|
32
26
|
|
|
33
|
-
- `pip install
|
|
27
|
+
- `pip install pixeltable-yolox`
|
|
34
28
|
|
|
35
29
|
Args:
|
|
36
30
|
model_id: one of: `yolox_nano`, `yolox_tiny`, `yolox_s`, `yolox_m`, `yolox_l`, `yolox_x`
|
|
@@ -46,31 +40,14 @@ def yolox(images: Batch[PIL.Image.Image], *, model_id: str, threshold: float = 0
|
|
|
46
40
|
>>> tbl.add_computed_column(detections=yolox(tbl.image, model_id='yolox_m', threshold=0.8))
|
|
47
41
|
"""
|
|
48
42
|
import torch
|
|
49
|
-
from yolox.utils import postprocess # type: ignore[import-untyped]
|
|
50
|
-
|
|
51
|
-
model, exp = _lookup_model(model_id, 'cpu')
|
|
52
|
-
image_tensors = list(_images_to_tensors(images, exp))
|
|
53
|
-
batch_tensor = torch.stack(image_tensors)
|
|
54
43
|
|
|
44
|
+
model = _lookup_model(model_id, 'cpu')
|
|
45
|
+
processor = _lookup_processor(model_id)
|
|
46
|
+
normalized_images = [normalize_image_mode(image) for image in images]
|
|
55
47
|
with torch.no_grad():
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
results: list[dict] = []
|
|
61
|
-
for image in images:
|
|
62
|
-
ratio = min(exp.test_size[0] / image.height, exp.test_size[1] / image.width)
|
|
63
|
-
if outputs[0] is None:
|
|
64
|
-
results.append({'bboxes': [], 'scores': [], 'labels': []})
|
|
65
|
-
else:
|
|
66
|
-
results.append(
|
|
67
|
-
{
|
|
68
|
-
'bboxes': [(output[:4] / ratio).tolist() for output in outputs[0]],
|
|
69
|
-
'scores': [output[4].item() * output[5].item() for output in outputs[0]],
|
|
70
|
-
'labels': [int(output[6]) for output in outputs[0]],
|
|
71
|
-
}
|
|
72
|
-
)
|
|
73
|
-
return results
|
|
48
|
+
tensor = processor(normalized_images)
|
|
49
|
+
output = model(tensor)
|
|
50
|
+
return processor.postprocess(normalized_images, output, threshold=threshold)
|
|
74
51
|
|
|
75
52
|
|
|
76
53
|
@pxt.udf
|
|
@@ -107,51 +84,31 @@ def yolo_to_coco(detections: dict) -> list:
|
|
|
107
84
|
return result
|
|
108
85
|
|
|
109
86
|
|
|
110
|
-
def
|
|
111
|
-
import
|
|
112
|
-
from yolox.data import ValTransform # type: ignore[import-untyped]
|
|
113
|
-
|
|
114
|
-
val_transform = ValTransform(legacy=False)
|
|
115
|
-
for image in images:
|
|
116
|
-
normalized_image = normalize_image_mode(image)
|
|
117
|
-
image_transform, _ = val_transform(np.array(normalized_image), None, exp.test_size)
|
|
118
|
-
yield torch.from_numpy(image_transform)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
def _lookup_model(model_id: str, device: str) -> tuple['YOLOX', 'Exp']:
|
|
122
|
-
import torch
|
|
123
|
-
from yolox.exp import get_exp
|
|
87
|
+
def _lookup_model(model_id: str, device: str) -> 'Yolox':
|
|
88
|
+
from yolox.models import Yolox
|
|
124
89
|
|
|
125
90
|
key = (model_id, device)
|
|
126
|
-
if key in _model_cache:
|
|
127
|
-
|
|
91
|
+
if key not in _model_cache:
|
|
92
|
+
_model_cache[key] = Yolox.from_pretrained(model_id, device=device)
|
|
128
93
|
|
|
129
|
-
|
|
130
|
-
weights_file = Path(f'{env.Env.get().tmp_dir}/{model_id}.pth')
|
|
131
|
-
if not weights_file.exists():
|
|
132
|
-
_logger.info(f'Downloading weights for YOLOX model {model_id}: from {weights_url} -> {weights_file}')
|
|
133
|
-
urlretrieve(weights_url, weights_file)
|
|
94
|
+
return _model_cache[key]
|
|
134
95
|
|
|
135
|
-
exp = get_exp(exp_name=model_id)
|
|
136
|
-
model = exp.get_model().to(device)
|
|
137
96
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
model.training = False
|
|
97
|
+
def _lookup_processor(model_id: str) -> 'YoloxProcessor':
|
|
98
|
+
from yolox.models import YoloxProcessor
|
|
141
99
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
model.load_state_dict(weights['model'])
|
|
100
|
+
if model_id not in _processor_cache:
|
|
101
|
+
_processor_cache[model_id] = YoloxProcessor(model_id)
|
|
145
102
|
|
|
146
|
-
|
|
147
|
-
return model, exp
|
|
103
|
+
return _processor_cache[model_id]
|
|
148
104
|
|
|
149
105
|
|
|
150
|
-
_model_cache: dict[tuple[str, str],
|
|
106
|
+
_model_cache: dict[tuple[str, str], 'Yolox'] = {}
|
|
107
|
+
_processor_cache: dict[str, 'YoloxProcessor'] = {}
|
|
151
108
|
|
|
152
109
|
|
|
153
110
|
__all__ = local_public_names(__name__)
|
|
154
111
|
|
|
155
112
|
|
|
156
|
-
def __dir__():
|
|
113
|
+
def __dir__() -> list[str]:
|
|
157
114
|
return __all__
|
|
@@ -252,7 +252,7 @@ def uda(
|
|
|
252
252
|
) -> Callable[[type[Aggregator]], AggregateFunction]: ...
|
|
253
253
|
|
|
254
254
|
|
|
255
|
-
def uda(*args, **kwargs):
|
|
255
|
+
def uda(*args, **kwargs): # type: ignore[no-untyped-def]
|
|
256
256
|
"""Decorator for user-defined aggregate functions.
|
|
257
257
|
|
|
258
258
|
The decorated class must inherit from Aggregator and implement the following methods:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import asyncio
|
|
4
3
|
import inspect
|
|
5
4
|
from typing import TYPE_CHECKING, Any, Callable, Optional, Sequence
|
|
6
5
|
from uuid import UUID
|
|
@@ -127,12 +126,10 @@ class CallableFunction(Function):
|
|
|
127
126
|
"""
|
|
128
127
|
assert self.is_batched
|
|
129
128
|
assert not self.is_polymorphic
|
|
129
|
+
assert not self.is_async
|
|
130
130
|
# Unpack the constant parameters
|
|
131
131
|
constant_kwargs, batched_kwargs = self.create_batch_kwargs(kwargs)
|
|
132
|
-
|
|
133
|
-
return asyncio.run(self.py_fn(*args, **constant_kwargs, **batched_kwargs))
|
|
134
|
-
else:
|
|
135
|
-
return self.py_fn(*args, **constant_kwargs, **batched_kwargs)
|
|
132
|
+
return self.py_fn(*args, **constant_kwargs, **batched_kwargs)
|
|
136
133
|
|
|
137
134
|
def create_batch_kwargs(self, kwargs: dict[str, Any]) -> tuple[dict[str, Any], dict[str, list[Any]]]:
|
|
138
135
|
"""Converts kwargs containing lists into constant and batched kwargs in the format expected by a batched udf."""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Any, Optional, Sequence
|
|
2
2
|
|
|
3
|
-
from pixeltable import exceptions as excs, exprs
|
|
3
|
+
from pixeltable import exceptions as excs, exprs, type_system as ts
|
|
4
4
|
|
|
5
5
|
from .function import Function
|
|
6
6
|
from .signature import Signature
|
|
@@ -76,9 +76,25 @@ class ExprTemplateFunction(Function):
|
|
|
76
76
|
arg_expr = arg
|
|
77
77
|
arg_exprs[param_expr] = arg_expr
|
|
78
78
|
result = result.substitute(arg_exprs)
|
|
79
|
-
assert not result._contains(exprs.Variable)
|
|
80
79
|
return result
|
|
81
80
|
|
|
81
|
+
def call_return_type(self, bound_args: dict[str, 'exprs.Expr']) -> ts.ColumnType:
|
|
82
|
+
"""
|
|
83
|
+
The call_return_type of an ExprTemplateFunction is derived from the template expression's col_type after
|
|
84
|
+
substitution (unlike for UDFs, whose call_return_type is derived from an explicitly specified
|
|
85
|
+
conditional_return_type).
|
|
86
|
+
"""
|
|
87
|
+
assert not self.is_polymorphic
|
|
88
|
+
template = self.template
|
|
89
|
+
with_defaults = bound_args.copy()
|
|
90
|
+
with_defaults.update(
|
|
91
|
+
{param_name: default for param_name, default in template.defaults.items() if param_name not in bound_args}
|
|
92
|
+
)
|
|
93
|
+
substituted_expr = self.template.expr.copy().substitute(
|
|
94
|
+
{template.param_exprs[name]: expr for name, expr in with_defaults.items()}
|
|
95
|
+
)
|
|
96
|
+
return substituted_expr.col_type
|
|
97
|
+
|
|
82
98
|
def _docstring(self) -> Optional[str]:
|
|
83
99
|
if isinstance(self.templates[0].expr, exprs.FunctionCall):
|
|
84
100
|
return self.templates[0].expr.fn._docstring()
|
|
@@ -97,6 +113,10 @@ class ExprTemplateFunction(Function):
|
|
|
97
113
|
|
|
98
114
|
@property
|
|
99
115
|
def display_name(self) -> str:
|
|
116
|
+
if not self.self_name and isinstance(self.templates[0].expr, exprs.FunctionCall):
|
|
117
|
+
# In the common case where the templated expression is itself a FunctionCall,
|
|
118
|
+
# fall back on the display name of the underlying FunctionCall
|
|
119
|
+
return self.templates[0].expr.fn.display_name
|
|
100
120
|
return self.self_name
|
|
101
121
|
|
|
102
122
|
@property
|
pixeltable/func/function.py
CHANGED
|
@@ -10,7 +10,6 @@ from typing import TYPE_CHECKING, Any, Callable, Optional, Sequence, cast
|
|
|
10
10
|
import sqlalchemy as sql
|
|
11
11
|
from typing_extensions import Self
|
|
12
12
|
|
|
13
|
-
import pixeltable as pxt
|
|
14
13
|
import pixeltable.exceptions as excs
|
|
15
14
|
import pixeltable.type_system as ts
|
|
16
15
|
|
|
@@ -155,7 +154,7 @@ class Function(ABC):
|
|
|
155
154
|
"""
|
|
156
155
|
raise NotImplementedError()
|
|
157
156
|
|
|
158
|
-
def __call__(self, *args: Any, **kwargs: Any) -> '
|
|
157
|
+
def __call__(self, *args: Any, **kwargs: Any) -> 'exprs.FunctionCall':
|
|
159
158
|
from pixeltable import exprs
|
|
160
159
|
|
|
161
160
|
args = [exprs.Expr.from_object(arg) for arg in args]
|
|
@@ -246,7 +245,7 @@ class Function(ABC):
|
|
|
246
245
|
# `None` when any of its non-nullable inputs are `None`.
|
|
247
246
|
for arg_name, arg in bound_args.items():
|
|
248
247
|
param = self.signature.parameters[arg_name]
|
|
249
|
-
if param.kind in
|
|
248
|
+
if param.kind in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD):
|
|
250
249
|
continue
|
|
251
250
|
if arg.col_type.nullable and not param.col_type.nullable:
|
|
252
251
|
return_type = return_type.copy(nullable=True)
|
|
@@ -385,10 +384,10 @@ class Function(ABC):
|
|
|
385
384
|
else:
|
|
386
385
|
var = exprs.Variable(name, param.col_type)
|
|
387
386
|
bindings[name] = var
|
|
388
|
-
if args_ok and param.kind in
|
|
387
|
+
if args_ok and param.kind in (
|
|
389
388
|
inspect.Parameter.POSITIONAL_ONLY,
|
|
390
389
|
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
|
391
|
-
|
|
390
|
+
):
|
|
392
391
|
template_args.append(var)
|
|
393
392
|
else:
|
|
394
393
|
template_kwargs[name] = var
|
|
@@ -31,7 +31,7 @@ class FunctionRegistry:
|
|
|
31
31
|
cls._instance = FunctionRegistry()
|
|
32
32
|
return cls._instance
|
|
33
33
|
|
|
34
|
-
def __init__(self):
|
|
34
|
+
def __init__(self) -> None:
|
|
35
35
|
self.stored_fns_by_id: dict[UUID, Function] = {}
|
|
36
36
|
self.module_fns: dict[str, Function] = {} # fqn -> Function
|
|
37
37
|
self.type_methods: dict[ts.ColumnType.Type, dict[str, Function]] = {}
|
pixeltable/func/signature.py
CHANGED
|
@@ -253,7 +253,7 @@ class Signature:
|
|
|
253
253
|
continue # skip 'self' or 'cls' parameter
|
|
254
254
|
if param.name in cls.SPECIAL_PARAM_NAMES:
|
|
255
255
|
raise excs.Error(f'{param.name!r} is a reserved parameter name')
|
|
256
|
-
if param.kind in
|
|
256
|
+
if param.kind in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD):
|
|
257
257
|
parameters.append(Parameter(param.name, col_type=None, kind=param.kind))
|
|
258
258
|
continue
|
|
259
259
|
|
pixeltable/func/tools.py
CHANGED
|
@@ -51,10 +51,10 @@ class Tool(pydantic.BaseModel):
|
|
|
51
51
|
# The output of `tool_calls` must be a dict in standardized tool invocation format:
|
|
52
52
|
# {tool_name: [{'args': {name1: value1, name2: value2, ...}}, ...], ...}
|
|
53
53
|
def invoke(self, tool_calls: 'exprs.Expr') -> 'exprs.Expr':
|
|
54
|
-
|
|
54
|
+
import pixeltable.functions as pxtf
|
|
55
55
|
|
|
56
56
|
func_name = self.name or self.fn.name
|
|
57
|
-
return
|
|
57
|
+
return pxtf.map(tool_calls[func_name]['*'], lambda x: self.__invoke_kwargs(x.args))
|
|
58
58
|
|
|
59
59
|
def __invoke_kwargs(self, kwargs: 'exprs.Expr') -> 'exprs.FunctionCall':
|
|
60
60
|
kwargs = {param.name: self.__extract_tool_arg(param, kwargs) for param in self.parameters.values()}
|
pixeltable/func/udf.py
CHANGED
|
@@ -43,7 +43,7 @@ def udf(
|
|
|
43
43
|
) -> ExprTemplateFunction: ...
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
def udf(*args, **kwargs):
|
|
46
|
+
def udf(*args, **kwargs): # type: ignore[no-untyped-def]
|
|
47
47
|
"""A decorator to create a Function from a function definition.
|
|
48
48
|
|
|
49
49
|
Examples:
|
|
@@ -79,7 +79,7 @@ def udf(*args, **kwargs):
|
|
|
79
79
|
if len(args) > 0:
|
|
80
80
|
raise excs.Error('Unexpected @udf decorator arguments.')
|
|
81
81
|
|
|
82
|
-
def decorator(decorated_fn: Callable):
|
|
82
|
+
def decorator(decorated_fn: Callable) -> CallableFunction:
|
|
83
83
|
return make_function(
|
|
84
84
|
decorated_fn,
|
|
85
85
|
batch_size=batch_size,
|
pixeltable/functions/__init__.py
CHANGED
|
@@ -24,10 +24,10 @@ from . import (
|
|
|
24
24
|
vision,
|
|
25
25
|
whisper,
|
|
26
26
|
)
|
|
27
|
-
from .globals import count, max, mean, min, sum
|
|
27
|
+
from .globals import count, map, max, mean, min, sum
|
|
28
28
|
|
|
29
29
|
__all__ = local_public_names(__name__, exclude=['globals']) + local_public_names(globals.__name__)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def __dir__():
|
|
32
|
+
def __dir__() -> list[str]:
|
|
33
33
|
return __all__
|
|
@@ -39,7 +39,7 @@ def _anthropic_client() -> 'anthropic.AsyncAnthropic':
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
class AnthropicRateLimitsInfo(env.RateLimitsInfo):
|
|
42
|
-
def __init__(self):
|
|
42
|
+
def __init__(self) -> None:
|
|
43
43
|
super().__init__(self._get_request_resources)
|
|
44
44
|
|
|
45
45
|
def _get_request_resources(self, messages: dict, max_tokens: int) -> dict[str, int]:
|
|
@@ -236,5 +236,5 @@ def _opt(arg: _T) -> Union[_T, 'anthropic.NotGiven']:
|
|
|
236
236
|
__all__ = local_public_names(__name__)
|
|
237
237
|
|
|
238
238
|
|
|
239
|
-
def __dir__():
|
|
239
|
+
def __dir__() -> list[str]:
|
|
240
240
|
return __all__
|
pixeltable/functions/audio.py
CHANGED
pixeltable/functions/deepseek.py
CHANGED
pixeltable/functions/globals.py
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import builtins
|
|
2
2
|
import typing
|
|
3
|
-
|
|
4
|
-
from typing import _GenericAlias # type: ignore[attr-defined] # isort: skip
|
|
5
|
-
from typing import Optional, Union
|
|
3
|
+
from typing import Any, Callable, Optional, Union
|
|
6
4
|
|
|
7
5
|
import sqlalchemy as sql
|
|
8
6
|
|
|
9
|
-
import
|
|
10
|
-
from pixeltable import exprs, func
|
|
7
|
+
from pixeltable import exceptions as excs, exprs, func, type_system as ts
|
|
11
8
|
from pixeltable.utils.code import local_public_names
|
|
12
9
|
|
|
10
|
+
from typing import _GenericAlias # type: ignore[attr-defined] # isort: skip
|
|
11
|
+
|
|
13
12
|
|
|
14
13
|
# TODO: remove and replace calls with astype()
|
|
15
14
|
def cast(expr: exprs.Expr, target_type: Union[ts.ColumnType, type, _GenericAlias]) -> exprs.Expr:
|
|
@@ -24,7 +23,7 @@ T = typing.TypeVar('T')
|
|
|
24
23
|
class sum(func.Aggregator, typing.Generic[T]):
|
|
25
24
|
"""Sums the selected integers or floats."""
|
|
26
25
|
|
|
27
|
-
def __init__(self):
|
|
26
|
+
def __init__(self) -> None:
|
|
28
27
|
self.sum: T = None
|
|
29
28
|
|
|
30
29
|
def update(self, val: T) -> None:
|
|
@@ -68,7 +67,7 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
|
|
|
68
67
|
),
|
|
69
68
|
)
|
|
70
69
|
class count(func.Aggregator, typing.Generic[T]):
|
|
71
|
-
def __init__(self):
|
|
70
|
+
def __init__(self) -> None:
|
|
72
71
|
self.count = 0
|
|
73
72
|
|
|
74
73
|
def update(self, val: T) -> None:
|
|
@@ -89,7 +88,7 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
|
|
|
89
88
|
type_substitutions=tuple({T: Optional[t]} for t in (str, int, float, bool, ts.Timestamp)), # type: ignore[misc]
|
|
90
89
|
)
|
|
91
90
|
class min(func.Aggregator, typing.Generic[T]):
|
|
92
|
-
def __init__(self):
|
|
91
|
+
def __init__(self) -> None:
|
|
93
92
|
self.val: T = None
|
|
94
93
|
|
|
95
94
|
def update(self, val: T) -> None:
|
|
@@ -119,7 +118,7 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
|
|
|
119
118
|
type_substitutions=tuple({T: Optional[t]} for t in (str, int, float, bool, ts.Timestamp)), # type: ignore[misc]
|
|
120
119
|
)
|
|
121
120
|
class max(func.Aggregator, typing.Generic[T]):
|
|
122
|
-
def __init__(self):
|
|
121
|
+
def __init__(self) -> None:
|
|
123
122
|
self.val: T = None
|
|
124
123
|
|
|
125
124
|
def update(self, val: T) -> None:
|
|
@@ -144,7 +143,7 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
|
|
|
144
143
|
|
|
145
144
|
@func.uda(type_substitutions=({T: Optional[int]}, {T: Optional[float]})) # type: ignore[misc]
|
|
146
145
|
class mean(func.Aggregator, typing.Generic[T]):
|
|
147
|
-
def __init__(self):
|
|
146
|
+
def __init__(self) -> None:
|
|
148
147
|
self.sum: T = None
|
|
149
148
|
self.count = 0
|
|
150
149
|
|
|
@@ -168,8 +167,20 @@ def _(val: sql.ColumnElement) -> Optional[sql.ColumnElement]:
|
|
|
168
167
|
return sql.sql.func.avg(val)
|
|
169
168
|
|
|
170
169
|
|
|
170
|
+
def map(expr: exprs.Expr, fn: Callable[[exprs.Expr], Any]) -> exprs.Expr:
|
|
171
|
+
target_expr: exprs.Expr
|
|
172
|
+
try:
|
|
173
|
+
target_expr = exprs.Expr.from_object(fn(exprs.json_path.RELATIVE_PATH_ROOT))
|
|
174
|
+
except Exception as e:
|
|
175
|
+
raise excs.Error(
|
|
176
|
+
'Failed to evaluate map function. '
|
|
177
|
+
'(The `fn` argument to `map()` must produce a valid Pixeltable expression.)'
|
|
178
|
+
) from e
|
|
179
|
+
return exprs.JsonMapper(expr, target_expr)
|
|
180
|
+
|
|
181
|
+
|
|
171
182
|
__all__ = local_public_names(__name__)
|
|
172
183
|
|
|
173
184
|
|
|
174
|
-
def __dir__():
|
|
185
|
+
def __dir__() -> list[str]:
|
|
175
186
|
return __all__
|
pixeltable/functions/image.py
CHANGED
pixeltable/functions/json.py
CHANGED
pixeltable/functions/math.py
CHANGED
pixeltable/functions/ollama.py
CHANGED
pixeltable/functions/openai.py
CHANGED
|
@@ -122,7 +122,7 @@ class OpenAIRateLimitsInfo(env.RateLimitsInfo):
|
|
|
122
122
|
_header_duration_pattern = re.compile(r'(?:(\d+)d)?(?:(\d+)h)?(?:(\d+)ms)|(?:(\d+)m)?(?:([\d.]+)s)?')
|
|
123
123
|
|
|
124
124
|
|
|
125
|
-
def _parse_header_duration(duration_str):
|
|
125
|
+
def _parse_header_duration(duration_str: str) -> datetime.timedelta:
|
|
126
126
|
match = _header_duration_pattern.match(duration_str)
|
|
127
127
|
if not match:
|
|
128
128
|
raise ValueError('Invalid duration format')
|
|
@@ -837,5 +837,5 @@ def _opt(arg: _T) -> Union[_T, 'openai.NotGiven']:
|
|
|
837
837
|
__all__ = local_public_names(__name__)
|
|
838
838
|
|
|
839
839
|
|
|
840
|
-
def __dir__():
|
|
840
|
+
def __dir__() -> list[str]:
|
|
841
841
|
return __all__
|
pixeltable/functions/string.py
CHANGED
pixeltable/functions/together.py
CHANGED
pixeltable/functions/util.py
CHANGED
|
@@ -21,7 +21,7 @@ def normalize_image_mode(image: PIL.Image.Image) -> PIL.Image.Image:
|
|
|
21
21
|
Converts grayscale images to 3-channel for compatibility with models that only work with
|
|
22
22
|
multichannel input.
|
|
23
23
|
"""
|
|
24
|
-
if image.mode in
|
|
24
|
+
if image.mode in ('1', 'L'):
|
|
25
25
|
return image.convert('RGB')
|
|
26
26
|
if image.mode == 'LA':
|
|
27
27
|
return image.convert('RGBA')
|
pixeltable/functions/video.py
CHANGED
|
@@ -143,7 +143,7 @@ def _get_metadata(path: str) -> dict:
|
|
|
143
143
|
|
|
144
144
|
|
|
145
145
|
def __get_stream_metadata(stream: av.stream.Stream) -> dict:
|
|
146
|
-
if stream.type not in
|
|
146
|
+
if stream.type not in ('audio', 'video'):
|
|
147
147
|
return {'type': stream.type} # Currently unsupported
|
|
148
148
|
|
|
149
149
|
codec_context = stream.codec_context
|
|
@@ -190,5 +190,5 @@ def __get_stream_metadata(stream: av.stream.Stream) -> dict:
|
|
|
190
190
|
__all__ = local_public_names(__name__)
|
|
191
191
|
|
|
192
192
|
|
|
193
|
-
def __dir__():
|
|
193
|
+
def __dir__() -> list[str]:
|
|
194
194
|
return __all__
|
pixeltable/functions/vision.py
CHANGED
|
@@ -238,7 +238,7 @@ class mean_ap(pxt.Aggregator):
|
|
|
238
238
|
- A `dict[int, float]` mapping each label class to an average precision (AP) value for that class.
|
|
239
239
|
"""
|
|
240
240
|
|
|
241
|
-
def __init__(self):
|
|
241
|
+
def __init__(self) -> None:
|
|
242
242
|
self.class_tpfp: dict[int, list[dict]] = defaultdict(list)
|
|
243
243
|
|
|
244
244
|
def update(self, eval_dicts: list[dict]) -> None:
|
|
@@ -394,5 +394,5 @@ def draw_bounding_boxes(
|
|
|
394
394
|
__all__ = local_public_names(__name__)
|
|
395
395
|
|
|
396
396
|
|
|
397
|
-
def __dir__():
|
|
397
|
+
def __dir__() -> list[str]:
|
|
398
398
|
return __all__
|