pixeltable 0.2.12__py3-none-any.whl → 0.2.14__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 +2 -2
- pixeltable/catalog/column.py +5 -0
- pixeltable/catalog/globals.py +8 -0
- pixeltable/catalog/insertable_table.py +2 -2
- pixeltable/catalog/table.py +27 -9
- pixeltable/catalog/table_version.py +41 -68
- pixeltable/catalog/view.py +3 -3
- pixeltable/dataframe.py +7 -6
- pixeltable/exec/__init__.py +2 -1
- pixeltable/exec/expr_eval_node.py +8 -1
- pixeltable/exec/row_update_node.py +61 -0
- pixeltable/exec/{sql_scan_node.py → sql_node.py} +120 -56
- pixeltable/exprs/__init__.py +1 -2
- pixeltable/exprs/comparison.py +5 -5
- pixeltable/exprs/compound_predicate.py +12 -12
- pixeltable/exprs/expr.py +67 -22
- pixeltable/exprs/function_call.py +60 -29
- pixeltable/exprs/globals.py +2 -0
- pixeltable/exprs/in_predicate.py +3 -3
- pixeltable/exprs/inline_array.py +18 -11
- pixeltable/exprs/is_null.py +5 -5
- pixeltable/exprs/method_ref.py +63 -0
- pixeltable/ext/__init__.py +9 -0
- pixeltable/ext/functions/__init__.py +8 -0
- pixeltable/ext/functions/whisperx.py +45 -5
- pixeltable/ext/functions/yolox.py +60 -14
- pixeltable/func/aggregate_function.py +10 -4
- pixeltable/func/callable_function.py +16 -4
- pixeltable/func/expr_template_function.py +1 -1
- pixeltable/func/function.py +12 -2
- pixeltable/func/function_registry.py +26 -9
- pixeltable/func/udf.py +32 -4
- pixeltable/functions/__init__.py +1 -1
- pixeltable/functions/fireworks.py +33 -0
- pixeltable/functions/globals.py +36 -1
- pixeltable/functions/huggingface.py +155 -7
- pixeltable/functions/image.py +242 -40
- pixeltable/functions/openai.py +214 -0
- pixeltable/functions/string.py +600 -8
- pixeltable/functions/timestamp.py +210 -0
- pixeltable/functions/together.py +106 -0
- pixeltable/functions/video.py +28 -10
- pixeltable/functions/whisper.py +32 -0
- pixeltable/globals.py +3 -3
- pixeltable/io/__init__.py +1 -1
- pixeltable/io/globals.py +186 -5
- pixeltable/io/label_studio.py +42 -2
- pixeltable/io/pandas.py +70 -34
- pixeltable/metadata/__init__.py +1 -1
- pixeltable/metadata/converters/convert_18.py +39 -0
- pixeltable/metadata/notes.py +10 -0
- pixeltable/plan.py +82 -7
- pixeltable/tool/create_test_db_dump.py +4 -5
- pixeltable/tool/doc_plugins/griffe.py +81 -0
- pixeltable/tool/doc_plugins/mkdocstrings.py +6 -0
- pixeltable/tool/doc_plugins/templates/material/udf.html.jinja +135 -0
- pixeltable/type_system.py +15 -14
- pixeltable/utils/s3.py +1 -1
- pixeltable-0.2.14.dist-info/METADATA +206 -0
- {pixeltable-0.2.12.dist-info → pixeltable-0.2.14.dist-info}/RECORD +64 -56
- pixeltable-0.2.14.dist-info/entry_points.txt +3 -0
- pixeltable/exprs/image_member_access.py +0 -96
- pixeltable/exprs/predicate.py +0 -44
- pixeltable-0.2.12.dist-info/METADATA +0 -137
- {pixeltable-0.2.12.dist-info → pixeltable-0.2.14.dist-info}/LICENSE +0 -0
- {pixeltable-0.2.12.dist-info → pixeltable-0.2.14.dist-info}/WHEEL +0 -0
pixeltable/functions/image.py
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pixeltable [UDFs](https://pixeltable.readme.io/docs/user-defined-functions-udfs) for `ImageType`.
|
|
3
|
+
|
|
4
|
+
Example:
|
|
5
|
+
```python
|
|
6
|
+
import pixeltable as pxt
|
|
7
|
+
|
|
8
|
+
t = pxt.get_table(...)
|
|
9
|
+
t.select(t.img_col.convert('L')).collect()
|
|
10
|
+
```
|
|
11
|
+
"""
|
|
12
|
+
|
|
1
13
|
import base64
|
|
2
|
-
from typing import Optional
|
|
14
|
+
from typing import Optional
|
|
3
15
|
|
|
4
16
|
import PIL.Image
|
|
5
17
|
|
|
@@ -9,9 +21,15 @@ from pixeltable.utils.code import local_public_names
|
|
|
9
21
|
from pixeltable.exprs import Expr
|
|
10
22
|
|
|
11
23
|
|
|
12
|
-
@func.udf
|
|
24
|
+
@func.udf(is_method=True)
|
|
13
25
|
def b64_encode(img: PIL.Image.Image, image_format: str = 'png') -> str:
|
|
14
|
-
|
|
26
|
+
"""
|
|
27
|
+
Convert image to a base64-encoded string.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
img: image
|
|
31
|
+
image_format: image format [supported by PIL](https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#fully-supported-formats)
|
|
32
|
+
"""
|
|
15
33
|
import io
|
|
16
34
|
|
|
17
35
|
bytes_arr = io.BytesIO()
|
|
@@ -20,27 +38,49 @@ def b64_encode(img: PIL.Image.Image, image_format: str = 'png') -> str:
|
|
|
20
38
|
return b64_bytes.decode('utf-8')
|
|
21
39
|
|
|
22
40
|
|
|
23
|
-
@func.udf(substitute_fn=PIL.Image.alpha_composite)
|
|
41
|
+
@func.udf(substitute_fn=PIL.Image.alpha_composite, is_method=True)
|
|
24
42
|
def alpha_composite(im1: PIL.Image.Image, im2: PIL.Image.Image) -> PIL.Image.Image:
|
|
43
|
+
"""
|
|
44
|
+
Alpha composite `im2` over `im1`.
|
|
45
|
+
|
|
46
|
+
Equivalent to [`PIL.Image.alpha_composite()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.alpha_composite)
|
|
47
|
+
"""
|
|
25
48
|
pass
|
|
26
49
|
|
|
27
50
|
|
|
28
|
-
@func.udf(substitute_fn=PIL.Image.blend)
|
|
51
|
+
@func.udf(substitute_fn=PIL.Image.blend, is_method=True)
|
|
29
52
|
def blend(im1: PIL.Image.Image, im2: PIL.Image.Image, alpha: float) -> PIL.Image.Image:
|
|
30
|
-
|
|
53
|
+
"""
|
|
54
|
+
Return a new image by interpolating between two input images, using a constant alpha.
|
|
31
55
|
|
|
56
|
+
Equivalent to [`PIL.Image.blend()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.blend)
|
|
57
|
+
"""
|
|
58
|
+
pass
|
|
32
59
|
|
|
33
|
-
@func.udf(substitute_fn=PIL.Image.composite)
|
|
60
|
+
@func.udf(substitute_fn=PIL.Image.composite, is_method=True)
|
|
34
61
|
def composite(image1: PIL.Image.Image, image2: PIL.Image.Image, mask: PIL.Image.Image) -> PIL.Image.Image:
|
|
62
|
+
"""
|
|
63
|
+
Return a composite image by blending two images using a mask.
|
|
64
|
+
|
|
65
|
+
Equivalent to [`PIL.Image.composite()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.composite)
|
|
66
|
+
"""
|
|
35
67
|
pass
|
|
36
68
|
|
|
37
69
|
|
|
38
70
|
# PIL.Image.Image methods
|
|
39
71
|
|
|
40
|
-
|
|
41
72
|
# Image.convert()
|
|
42
|
-
@func.udf
|
|
73
|
+
@func.udf(is_method=True)
|
|
43
74
|
def convert(self: PIL.Image.Image, mode: str) -> PIL.Image.Image:
|
|
75
|
+
"""
|
|
76
|
+
Convert the image to a different mode.
|
|
77
|
+
|
|
78
|
+
Equivalent to
|
|
79
|
+
[`PIL.Image.Image.convert()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.convert).
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
mode: The mode to convert to. See the [Pillow documentation](https://pillow.readthedocs.io/en/stable/handbook/concepts.html#concept-modes) for a list of supported modes.
|
|
83
|
+
"""
|
|
44
84
|
return self.convert(mode)
|
|
45
85
|
|
|
46
86
|
|
|
@@ -52,23 +92,39 @@ def _(self: Expr, mode: str) -> ts.ColumnType:
|
|
|
52
92
|
|
|
53
93
|
|
|
54
94
|
# Image.crop()
|
|
55
|
-
@func.udf(substitute_fn=PIL.Image.Image.crop, param_types=[ts.ImageType(), ts.ArrayType((4,), dtype=ts.IntType())])
|
|
56
|
-
def crop(self: PIL.Image.Image, box:
|
|
95
|
+
@func.udf(substitute_fn=PIL.Image.Image.crop, param_types=[ts.ImageType(), ts.ArrayType((4,), dtype=ts.IntType())], is_method=True)
|
|
96
|
+
def crop(self: PIL.Image.Image, box: tuple[int, int, int, int]) -> PIL.Image.Image:
|
|
97
|
+
"""
|
|
98
|
+
Return a rectangular region from the image. The box is a 4-tuple defining the left, upper, right, and lower pixel
|
|
99
|
+
coordinates.
|
|
100
|
+
|
|
101
|
+
Equivalent to
|
|
102
|
+
[`PIL.Image.Image.crop()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.crop)
|
|
103
|
+
"""
|
|
57
104
|
pass
|
|
58
105
|
|
|
59
106
|
|
|
60
107
|
@crop.conditional_return_type
|
|
61
|
-
def _(self: Expr, box:
|
|
108
|
+
def _(self: Expr, box: tuple[int, int, int, int]) -> ts.ColumnType:
|
|
62
109
|
input_type = self.col_type
|
|
63
110
|
assert isinstance(input_type, ts.ImageType)
|
|
64
|
-
if isinstance(box, list) and all(isinstance(x, int) for x in box):
|
|
111
|
+
if (isinstance(box, list) or isinstance(box, tuple)) and len(box) == 4 and all(isinstance(x, int) for x in box):
|
|
65
112
|
return ts.ImageType(size=(box[2] - box[0], box[3] - box[1]), mode=input_type.mode, nullable=input_type.nullable)
|
|
66
113
|
return ts.ImageType(mode=input_type.mode, nullable=input_type.nullable) # we can't compute the size statically
|
|
67
114
|
|
|
68
115
|
|
|
69
116
|
# Image.getchannel()
|
|
70
|
-
@func.udf(substitute_fn=PIL.Image.Image.getchannel)
|
|
117
|
+
@func.udf(substitute_fn=PIL.Image.Image.getchannel, is_method=True)
|
|
71
118
|
def getchannel(self: PIL.Image.Image, channel: int) -> PIL.Image.Image:
|
|
119
|
+
"""
|
|
120
|
+
Return an L-mode image containing a single channel of the original image.
|
|
121
|
+
|
|
122
|
+
Equivalent to
|
|
123
|
+
[`PIL.Image.Image.getchannel()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.getchannel)
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
channel: The channel to extract. This is a 0-based index.
|
|
127
|
+
"""
|
|
72
128
|
pass
|
|
73
129
|
|
|
74
130
|
|
|
@@ -80,31 +136,64 @@ def _(self: Expr) -> ts.ColumnType:
|
|
|
80
136
|
|
|
81
137
|
|
|
82
138
|
# Image.resize()
|
|
83
|
-
@func.udf(param_types=[ts.ImageType(), ts.ArrayType((2,), dtype=ts.IntType())])
|
|
84
|
-
def resize(self: PIL.Image.Image, size:
|
|
139
|
+
@func.udf(param_types=[ts.ImageType(), ts.ArrayType((2,), dtype=ts.IntType())], is_method=True)
|
|
140
|
+
def resize(self: PIL.Image.Image, size: tuple[int, int]) -> PIL.Image.Image:
|
|
141
|
+
"""
|
|
142
|
+
Return a resized copy of the image. The size parameter is a tuple containing the width and height of the new image.
|
|
143
|
+
|
|
144
|
+
Equivalent to
|
|
145
|
+
[`PIL.Image.Image.resize()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.resize)
|
|
146
|
+
"""
|
|
85
147
|
return self.resize(size)
|
|
86
148
|
|
|
87
149
|
|
|
88
150
|
@resize.conditional_return_type
|
|
89
|
-
def _(self: Expr, size:
|
|
151
|
+
def _(self: Expr, size: tuple[int, int]) -> ts.ColumnType:
|
|
90
152
|
input_type = self.col_type
|
|
91
153
|
assert isinstance(input_type, ts.ImageType)
|
|
92
154
|
return ts.ImageType(size=size, mode=input_type.mode, nullable=input_type.nullable)
|
|
93
155
|
|
|
94
156
|
|
|
95
157
|
# Image.rotate()
|
|
96
|
-
@func.udf
|
|
158
|
+
@func.udf(is_method=True)
|
|
97
159
|
def rotate(self: PIL.Image.Image, angle: int) -> PIL.Image.Image:
|
|
160
|
+
"""
|
|
161
|
+
Return a copy of the image rotated by the given angle.
|
|
162
|
+
|
|
163
|
+
Equivalent to
|
|
164
|
+
[`PIL.Image.Image.rotate()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.rotate)
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
angle: The angle to rotate the image, in degrees. Positive angles are counter-clockwise.
|
|
168
|
+
"""
|
|
98
169
|
return self.rotate(angle)
|
|
99
170
|
|
|
100
171
|
|
|
101
|
-
@func.udf(substitute_fn=PIL.Image.Image.effect_spread)
|
|
172
|
+
@func.udf(substitute_fn=PIL.Image.Image.effect_spread, is_method=True)
|
|
102
173
|
def effect_spread(self: PIL.Image.Image, distance: int) -> PIL.Image.Image:
|
|
174
|
+
"""
|
|
175
|
+
Randomly spread pixels in an image.
|
|
176
|
+
|
|
177
|
+
Equivalent to
|
|
178
|
+
[`PIL.Image.Image.effect_spread()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.effect_spread)
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
distance: The distance to spread pixels.
|
|
182
|
+
"""
|
|
103
183
|
pass
|
|
104
184
|
|
|
105
185
|
|
|
106
|
-
@func.udf(substitute_fn=PIL.Image.Image.transpose)
|
|
186
|
+
@func.udf(substitute_fn=PIL.Image.Image.transpose, is_method=True)
|
|
107
187
|
def transpose(self: PIL.Image.Image, method: int) -> PIL.Image.Image:
|
|
188
|
+
"""
|
|
189
|
+
Transpose the image.
|
|
190
|
+
|
|
191
|
+
Equivalent to
|
|
192
|
+
[`PIL.Image.Image.transpose()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.transpose)
|
|
193
|
+
|
|
194
|
+
Args:
|
|
195
|
+
method: The transpose method. See the [Pillow documentation](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.transpose) for a list of supported methods.
|
|
196
|
+
"""
|
|
108
197
|
pass
|
|
109
198
|
|
|
110
199
|
|
|
@@ -115,53 +204,128 @@ def _(self: Expr) -> ts.ColumnType:
|
|
|
115
204
|
return self.col_type
|
|
116
205
|
|
|
117
206
|
|
|
118
|
-
@func.udf(substitute_fn=PIL.Image.Image.entropy)
|
|
207
|
+
@func.udf(substitute_fn=PIL.Image.Image.entropy, is_method=True)
|
|
119
208
|
def entropy(self: PIL.Image.Image, mask: Optional[PIL.Image.Image] = None, extrema: Optional[list] = None) -> float:
|
|
209
|
+
"""
|
|
210
|
+
Returns the entropy of the image, optionally using a mask and extrema.
|
|
211
|
+
|
|
212
|
+
Equivalent to
|
|
213
|
+
[`PIL.Image.Image.entropy()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.entropy)
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
mask: An optional mask image.
|
|
217
|
+
extrema: An optional list of extrema.
|
|
218
|
+
"""
|
|
120
219
|
pass
|
|
121
220
|
|
|
122
221
|
|
|
123
|
-
@func.udf(substitute_fn=PIL.Image.Image.getbands)
|
|
124
|
-
def getbands(self: PIL.Image.Image) ->
|
|
222
|
+
@func.udf(substitute_fn=PIL.Image.Image.getbands, is_method=True)
|
|
223
|
+
def getbands(self: PIL.Image.Image) -> tuple[str]:
|
|
224
|
+
"""
|
|
225
|
+
Return a tuple containing the names of the image bands.
|
|
226
|
+
|
|
227
|
+
Equivalent to
|
|
228
|
+
[`PIL.Image.Image.getbands()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.getbands)
|
|
229
|
+
"""
|
|
125
230
|
pass
|
|
126
231
|
|
|
127
232
|
|
|
128
|
-
@func.udf(substitute_fn=PIL.Image.Image.getbbox)
|
|
129
|
-
def getbbox(self: PIL.Image.Image) ->
|
|
233
|
+
@func.udf(substitute_fn=PIL.Image.Image.getbbox, is_method=True)
|
|
234
|
+
def getbbox(self: PIL.Image.Image, *, alpha_only: bool = True) -> tuple[int, int, int, int]:
|
|
235
|
+
"""
|
|
236
|
+
Return a bounding box for the non-zero regions of the image.
|
|
237
|
+
|
|
238
|
+
Equivalent to [`PIL.Image.Image.getbbox()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.getbbox)
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
alpha_only: If `True`, and the image has an alpha channel, trim transparent pixels. Otherwise, trim pixels when all channels are zero.
|
|
242
|
+
"""
|
|
130
243
|
pass
|
|
131
244
|
|
|
132
245
|
|
|
133
|
-
@func.udf(substitute_fn=PIL.Image.Image.getcolors)
|
|
134
|
-
def getcolors(self: PIL.Image.Image, maxcolors: int) ->
|
|
246
|
+
@func.udf(substitute_fn=PIL.Image.Image.getcolors, is_method=True)
|
|
247
|
+
def getcolors(self: PIL.Image.Image, maxcolors: int = 256) -> tuple[tuple[int, int, int], int]:
|
|
248
|
+
"""
|
|
249
|
+
Return a list of colors used in the image, up to a maximum of `maxcolors`.
|
|
250
|
+
|
|
251
|
+
Equivalent to
|
|
252
|
+
[`PIL.Image.Image.getcolors()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.getcolors)
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
maxcolors: The maximum number of colors to return.
|
|
256
|
+
"""
|
|
135
257
|
pass
|
|
136
258
|
|
|
137
259
|
|
|
138
|
-
@func.udf(substitute_fn=PIL.Image.Image.getextrema)
|
|
139
|
-
def getextrema(self: PIL.Image.Image) ->
|
|
260
|
+
@func.udf(substitute_fn=PIL.Image.Image.getextrema, is_method=True)
|
|
261
|
+
def getextrema(self: PIL.Image.Image) -> tuple[int, int]:
|
|
262
|
+
"""
|
|
263
|
+
Return a 2-tuple containing the minimum and maximum pixel values of the image.
|
|
264
|
+
|
|
265
|
+
Equivalent to
|
|
266
|
+
[`PIL.Image.Image.getextrema()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.getextrema)
|
|
267
|
+
"""
|
|
140
268
|
pass
|
|
141
269
|
|
|
142
270
|
|
|
143
|
-
@func.udf(substitute_fn=PIL.Image.Image.getpalette)
|
|
144
|
-
def getpalette(self: PIL.Image.Image, mode: Optional[str] = None) ->
|
|
271
|
+
@func.udf(substitute_fn=PIL.Image.Image.getpalette, is_method=True)
|
|
272
|
+
def getpalette(self: PIL.Image.Image, mode: Optional[str] = None) -> tuple[int]:
|
|
273
|
+
"""
|
|
274
|
+
Return the palette of the image, optionally converting it to a different mode.
|
|
275
|
+
|
|
276
|
+
Equivalent to
|
|
277
|
+
[`PIL.Image.Image.getpalette()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.getpalette)
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
mode: The mode to convert the palette to.
|
|
281
|
+
"""
|
|
145
282
|
pass
|
|
146
283
|
|
|
147
284
|
|
|
148
|
-
@func.udf(param_types=[ts.ImageType(), ts.ArrayType((2,), dtype=ts.IntType())])
|
|
149
|
-
def getpixel(self: PIL.Image.Image, xy: tuple[int, int]) ->
|
|
285
|
+
@func.udf(param_types=[ts.ImageType(), ts.ArrayType((2,), dtype=ts.IntType())], is_method=True)
|
|
286
|
+
def getpixel(self: PIL.Image.Image, xy: tuple[int, int]) -> tuple[int]:
|
|
287
|
+
"""
|
|
288
|
+
Return the pixel value at the given position. The position `xy` is a tuple containing the x and y coordinates.
|
|
289
|
+
|
|
290
|
+
Equivalent to
|
|
291
|
+
[`PIL.Image.Image.getpixel()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.getpixel)
|
|
292
|
+
|
|
293
|
+
Args:
|
|
294
|
+
xy: The coordinates, given as (x, y).
|
|
295
|
+
"""
|
|
150
296
|
# `xy` will be a list; `tuple(xy)` is necessary for pillow 9 compatibility
|
|
151
297
|
return self.getpixel(tuple(xy))
|
|
152
298
|
|
|
153
299
|
|
|
154
|
-
@func.udf(substitute_fn=PIL.Image.Image.getprojection)
|
|
155
|
-
def getprojection(self: PIL.Image.Image) ->
|
|
300
|
+
@func.udf(substitute_fn=PIL.Image.Image.getprojection, is_method=True)
|
|
301
|
+
def getprojection(self: PIL.Image.Image) -> tuple[int]:
|
|
302
|
+
"""
|
|
303
|
+
Return two sequences representing the horizontal and vertical projection of the image.
|
|
304
|
+
|
|
305
|
+
Equivalent to
|
|
306
|
+
[`PIL.Image.Image.getprojection()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.getprojection)
|
|
307
|
+
"""
|
|
156
308
|
pass
|
|
157
309
|
|
|
158
310
|
|
|
159
|
-
@func.udf(substitute_fn=PIL.Image.Image.histogram)
|
|
160
|
-
def histogram(
|
|
311
|
+
@func.udf(substitute_fn=PIL.Image.Image.histogram, is_method=True)
|
|
312
|
+
def histogram(
|
|
313
|
+
self: PIL.Image.Image, mask: Optional[PIL.Image.Image] = None, extrema: Optional[list] = None
|
|
314
|
+
) -> list[int]:
|
|
315
|
+
"""
|
|
316
|
+
Return a histogram for the image.
|
|
317
|
+
|
|
318
|
+
Equivalent to
|
|
319
|
+
[`PIL.Image.Image.histogram()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.histogram)
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
mask: An optional mask image.
|
|
323
|
+
extrema: An optional list of extrema.
|
|
324
|
+
"""
|
|
161
325
|
pass
|
|
162
326
|
|
|
163
327
|
|
|
164
|
-
@func.udf(substitute_fn=PIL.Image.Image.quantize)
|
|
328
|
+
@func.udf(substitute_fn=PIL.Image.Image.quantize, is_method=True)
|
|
165
329
|
def quantize(
|
|
166
330
|
self: PIL.Image.Image,
|
|
167
331
|
colors: int = 256,
|
|
@@ -170,14 +334,52 @@ def quantize(
|
|
|
170
334
|
palette: Optional[int] = None,
|
|
171
335
|
dither: int = PIL.Image.Dither.FLOYDSTEINBERG,
|
|
172
336
|
) -> PIL.Image.Image:
|
|
337
|
+
"""
|
|
338
|
+
Convert the image to 'P' mode with the specified number of colors.
|
|
339
|
+
|
|
340
|
+
Equivalent to
|
|
341
|
+
[`PIL.Image.Image.quantize()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.quantize)
|
|
342
|
+
|
|
343
|
+
Args:
|
|
344
|
+
colors: The number of colors to quantize to.
|
|
345
|
+
method: The quantization method. See the [Pillow documentation](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.quantize) for a list of supported methods.
|
|
346
|
+
kmeans: The number of k-means clusters to use.
|
|
347
|
+
palette: The palette to use.
|
|
348
|
+
dither: The dithering method. See the [Pillow documentation](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.quantize) for a list of supported methods.
|
|
349
|
+
"""
|
|
173
350
|
pass
|
|
174
351
|
|
|
175
352
|
|
|
176
|
-
@func.udf(substitute_fn=PIL.Image.Image.reduce)
|
|
177
|
-
def reduce(self: PIL.Image.Image, factor: int, box: Optional[
|
|
353
|
+
@func.udf(substitute_fn=PIL.Image.Image.reduce, is_method=True)
|
|
354
|
+
def reduce(self: PIL.Image.Image, factor: int, box: Optional[tuple[int]] = None) -> PIL.Image.Image:
|
|
355
|
+
"""
|
|
356
|
+
Reduce the image by the given factor.
|
|
357
|
+
|
|
358
|
+
Equivalent to
|
|
359
|
+
[`PIL.Image.Image.reduce()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.reduce)
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
factor: The reduction factor.
|
|
363
|
+
box: An optional 4-tuple of ints providing the source image region to be reduced. The values must be within (0, 0, width, height) rectangle. If omitted or None, the entire source is used.
|
|
364
|
+
"""
|
|
178
365
|
pass
|
|
179
366
|
|
|
180
367
|
|
|
368
|
+
@func.udf(is_property=True)
|
|
369
|
+
def width(self: PIL.Image.Image) -> int:
|
|
370
|
+
return self.width
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
@func.udf(is_property=True)
|
|
374
|
+
def height(self: PIL.Image.Image) -> int:
|
|
375
|
+
return self.height
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
@func.udf(is_property=True)
|
|
379
|
+
def mode(self: PIL.Image.Image) -> str:
|
|
380
|
+
return self.mode
|
|
381
|
+
|
|
382
|
+
|
|
181
383
|
__all__ = local_public_names(__name__)
|
|
182
384
|
|
|
183
385
|
|
pixeltable/functions/openai.py
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pixeltable [UDFs](https://pixeltable.readme.io/docs/user-defined-functions-udfs)
|
|
3
|
+
that wrap various endpoints from the OpenAI API. In order to use them, you must
|
|
4
|
+
first `pip install openai` and configure your OpenAI credentials, as described in
|
|
5
|
+
the [Working with OpenAI](https://pixeltable.readme.io/docs/working-with-openai) tutorial.
|
|
6
|
+
"""
|
|
7
|
+
|
|
1
8
|
import base64
|
|
2
9
|
import io
|
|
3
10
|
import pathlib
|
|
@@ -51,6 +58,33 @@ def _retry(fn: Callable) -> Callable:
|
|
|
51
58
|
def speech(
|
|
52
59
|
input: str, *, model: str, voice: str, response_format: Optional[str] = None, speed: Optional[float] = None
|
|
53
60
|
) -> str:
|
|
61
|
+
"""
|
|
62
|
+
Generates audio from the input text.
|
|
63
|
+
|
|
64
|
+
Equivalent to the OpenAI `audio/speech` API endpoint.
|
|
65
|
+
For additional details, see: [https://platform.openai.com/docs/guides/text-to-speech](https://platform.openai.com/docs/guides/text-to-speech)
|
|
66
|
+
|
|
67
|
+
__Requirements:__
|
|
68
|
+
|
|
69
|
+
- `pip install openai`
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
input: The text to synthesize into speech.
|
|
73
|
+
model: The model to use for speech synthesis.
|
|
74
|
+
voice: The voice profile to use for speech synthesis. Supported options include:
|
|
75
|
+
`alloy`, `echo`, `fable`, `onyx`, `nova`, and `shimmer`.
|
|
76
|
+
|
|
77
|
+
For details on the other parameters, see: [https://platform.openai.com/docs/api-reference/audio/createSpeech](https://platform.openai.com/docs/api-reference/audio/createSpeech)
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
An audio file containing the synthesized speech.
|
|
81
|
+
|
|
82
|
+
Examples:
|
|
83
|
+
Add a computed column that applies the model `tts-1` to an existing Pixeltable column `tbl.text`
|
|
84
|
+
of the table `tbl`:
|
|
85
|
+
|
|
86
|
+
>>> tbl['audio'] = speech(tbl.text, model='tts-1', voice='nova')
|
|
87
|
+
"""
|
|
54
88
|
content = _retry(_openai_client().audio.speech.create)(
|
|
55
89
|
input=input, model=model, voice=voice, response_format=_opt(response_format), speed=_opt(speed)
|
|
56
90
|
)
|
|
@@ -77,6 +111,31 @@ def transcriptions(
|
|
|
77
111
|
prompt: Optional[str] = None,
|
|
78
112
|
temperature: Optional[float] = None,
|
|
79
113
|
) -> dict:
|
|
114
|
+
"""
|
|
115
|
+
Transcribes audio into the input language.
|
|
116
|
+
|
|
117
|
+
Equivalent to the OpenAI `audio/transcriptions` API endpoint.
|
|
118
|
+
For additional details, see: [https://platform.openai.com/docs/guides/speech-to-text](https://platform.openai.com/docs/guides/speech-to-text)
|
|
119
|
+
|
|
120
|
+
__Requirements:__
|
|
121
|
+
|
|
122
|
+
- `pip install openai`
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
audio: The audio to transcribe.
|
|
126
|
+
model: The model to use for speech transcription.
|
|
127
|
+
|
|
128
|
+
For details on the other parameters, see: [https://platform.openai.com/docs/api-reference/audio/createTranscription](https://platform.openai.com/docs/api-reference/audio/createTranscription)
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
A dictionary containing the transcription and other metadata.
|
|
132
|
+
|
|
133
|
+
Examples:
|
|
134
|
+
Add a computed column that applies the model `whisper-1` to an existing Pixeltable column `tbl.audio`
|
|
135
|
+
of the table `tbl`:
|
|
136
|
+
|
|
137
|
+
>>> tbl['transcription'] = transcriptions(tbl.audio, model='whisper-1', language='en')
|
|
138
|
+
"""
|
|
80
139
|
file = pathlib.Path(audio)
|
|
81
140
|
transcription = _retry(_openai_client().audio.transcriptions.create)(
|
|
82
141
|
file=file, model=model, language=_opt(language), prompt=_opt(prompt), temperature=_opt(temperature)
|
|
@@ -86,6 +145,31 @@ def transcriptions(
|
|
|
86
145
|
|
|
87
146
|
@pxt.udf(param_types=[ts.AudioType(), ts.StringType(), ts.StringType(nullable=True), ts.FloatType(nullable=True)])
|
|
88
147
|
def translations(audio: str, *, model: str, prompt: Optional[str] = None, temperature: Optional[float] = None) -> dict:
|
|
148
|
+
"""
|
|
149
|
+
Translates audio into English.
|
|
150
|
+
|
|
151
|
+
Equivalent to the OpenAI `audio/translations` API endpoint.
|
|
152
|
+
For additional details, see: [https://platform.openai.com/docs/guides/speech-to-text](https://platform.openai.com/docs/guides/speech-to-text)
|
|
153
|
+
|
|
154
|
+
__Requirements:__
|
|
155
|
+
|
|
156
|
+
- `pip install openai`
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
audio: The audio to translate.
|
|
160
|
+
model: The model to use for speech transcription and translation.
|
|
161
|
+
|
|
162
|
+
For details on the other parameters, see: [https://platform.openai.com/docs/api-reference/audio/createTranslation](https://platform.openai.com/docs/api-reference/audio/createTranslation)
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
A dictionary containing the translation and other metadata.
|
|
166
|
+
|
|
167
|
+
Examples:
|
|
168
|
+
Add a computed column that applies the model `whisper-1` to an existing Pixeltable column `tbl.audio`
|
|
169
|
+
of the table `tbl`:
|
|
170
|
+
|
|
171
|
+
>>> tbl['translation'] = translations(tbl.audio, model='whisper-1', language='en')
|
|
172
|
+
"""
|
|
89
173
|
file = pathlib.Path(audio)
|
|
90
174
|
translation = _retry(_openai_client().audio.translations.create)(
|
|
91
175
|
file=file, model=model, prompt=_opt(prompt), temperature=_opt(temperature)
|
|
@@ -118,6 +202,35 @@ def chat_completions(
|
|
|
118
202
|
tool_choice: Optional[dict] = None,
|
|
119
203
|
user: Optional[str] = None,
|
|
120
204
|
) -> dict:
|
|
205
|
+
"""
|
|
206
|
+
Creates a model response for the given chat conversation.
|
|
207
|
+
|
|
208
|
+
Equivalent to the OpenAI `chat/completions` API endpoint.
|
|
209
|
+
For additional details, see: [https://platform.openai.com/docs/guides/chat-completions](https://platform.openai.com/docs/guides/chat-completions)
|
|
210
|
+
|
|
211
|
+
__Requirements:__
|
|
212
|
+
|
|
213
|
+
- `pip install openai`
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
messages: A list of messages to use for chat completion, as described in the OpenAI API documentation.
|
|
217
|
+
model: The model to use for chat completion.
|
|
218
|
+
|
|
219
|
+
For details on the other parameters, see: [https://platform.openai.com/docs/api-reference/chat](https://platform.openai.com/docs/api-reference/chat)
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
A dictionary containing the response and other metadata.
|
|
223
|
+
|
|
224
|
+
Examples:
|
|
225
|
+
Add a computed column that applies the model `gpt-4o-mini` to an existing Pixeltable column `tbl.prompt`
|
|
226
|
+
of the table `tbl`:
|
|
227
|
+
|
|
228
|
+
>>> messages = [
|
|
229
|
+
{'role': 'system', 'content': 'You are a helpful assistant.'},
|
|
230
|
+
{'role': 'user', 'content': tbl.prompt}
|
|
231
|
+
]
|
|
232
|
+
tbl['response'] = chat_completions(messages, model='gpt-4o-mini')
|
|
233
|
+
"""
|
|
121
234
|
result = _retry(_openai_client().chat.completions.create)(
|
|
122
235
|
messages=messages,
|
|
123
236
|
model=model,
|
|
@@ -142,6 +255,30 @@ def chat_completions(
|
|
|
142
255
|
|
|
143
256
|
@pxt.udf
|
|
144
257
|
def vision(prompt: str, image: PIL.Image.Image, *, model: str) -> str:
|
|
258
|
+
"""
|
|
259
|
+
Analyzes an image with the OpenAI vision capability. This is a convenience function that takes an image and
|
|
260
|
+
prompt, and constructs a chat completion request that utilizes OpenAI vision.
|
|
261
|
+
|
|
262
|
+
For additional details, see: [https://platform.openai.com/docs/guides/vision](https://platform.openai.com/docs/guides/vision)
|
|
263
|
+
|
|
264
|
+
__Requirements:__
|
|
265
|
+
|
|
266
|
+
- `pip install openai`
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
prompt: A prompt for the OpenAI vision request.
|
|
270
|
+
image: The image to analyze.
|
|
271
|
+
model: The model to use for OpenAI vision.
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
The response from the OpenAI vision API.
|
|
275
|
+
|
|
276
|
+
Examples:
|
|
277
|
+
Add a computed column that applies the model `gpt-4o-mini` to an existing Pixeltable column `tbl.image`
|
|
278
|
+
of the table `tbl`:
|
|
279
|
+
|
|
280
|
+
>>> tbl['response'] = vision("What's in this image?", tbl.image, model='gpt-4o-mini')
|
|
281
|
+
"""
|
|
145
282
|
# TODO(aaron-siegel): Decompose CPU/GPU ops into separate functions
|
|
146
283
|
bytes_arr = io.BytesIO()
|
|
147
284
|
image.save(bytes_arr, format='png')
|
|
@@ -174,6 +311,33 @@ _embedding_dimensions_cache: dict[str, int] = {
|
|
|
174
311
|
def embeddings(
|
|
175
312
|
input: Batch[str], *, model: str, dimensions: Optional[int] = None, user: Optional[str] = None
|
|
176
313
|
) -> Batch[np.ndarray]:
|
|
314
|
+
"""
|
|
315
|
+
Creates an embedding vector representing the input text.
|
|
316
|
+
|
|
317
|
+
Equivalent to the OpenAI `embeddings` API endpoint.
|
|
318
|
+
For additional details, see: [https://platform.openai.com/docs/guides/embeddings](https://platform.openai.com/docs/guides/embeddings)
|
|
319
|
+
|
|
320
|
+
__Requirements:__
|
|
321
|
+
|
|
322
|
+
- `pip install openai`
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
input: The text to embed.
|
|
326
|
+
model: The model to use for the embedding.
|
|
327
|
+
dimensions: The vector length of the embedding. If not specified, Pixeltable will use
|
|
328
|
+
a default value based on the model.
|
|
329
|
+
|
|
330
|
+
For details on the other parameters, see: [https://platform.openai.com/docs/api-reference/embeddings](https://platform.openai.com/docs/api-reference/embeddings)
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
An array representing the application of the given embedding to `input`.
|
|
334
|
+
|
|
335
|
+
Examples:
|
|
336
|
+
Add a computed column that applies the model `text-embedding-3-small` to an existing
|
|
337
|
+
Pixeltable column `tbl.text` of the table `tbl`:
|
|
338
|
+
|
|
339
|
+
>>> tbl['embed'] = embeddings(tbl.text, model='text-embedding-3-small')
|
|
340
|
+
"""
|
|
177
341
|
result = _retry(_openai_client().embeddings.create)(
|
|
178
342
|
input=input, model=model, dimensions=_opt(dimensions), user=_opt(user), encoding_format='float'
|
|
179
343
|
)
|
|
@@ -204,6 +368,31 @@ def image_generations(
|
|
|
204
368
|
style: Optional[str] = None,
|
|
205
369
|
user: Optional[str] = None,
|
|
206
370
|
) -> PIL.Image.Image:
|
|
371
|
+
"""
|
|
372
|
+
Creates an image given a prompt.
|
|
373
|
+
|
|
374
|
+
Equivalent to the OpenAI `images/generations` API endpoint.
|
|
375
|
+
For additional details, see: [https://platform.openai.com/docs/guides/images](https://platform.openai.com/docs/guides/images)
|
|
376
|
+
|
|
377
|
+
__Requirements:__
|
|
378
|
+
|
|
379
|
+
- `pip install openai`
|
|
380
|
+
|
|
381
|
+
Args:
|
|
382
|
+
prompt: Prompt for the image.
|
|
383
|
+
model: The model to use for the generations.
|
|
384
|
+
|
|
385
|
+
For details on the other parameters, see: [https://platform.openai.com/docs/api-reference/images/create](https://platform.openai.com/docs/api-reference/images/create)
|
|
386
|
+
|
|
387
|
+
Returns:
|
|
388
|
+
The generated image.
|
|
389
|
+
|
|
390
|
+
Examples:
|
|
391
|
+
Add a computed column that applies the model `dall-e-2` to an existing
|
|
392
|
+
Pixeltable column `tbl.text` of the table `tbl`:
|
|
393
|
+
|
|
394
|
+
>>> tbl['gen_image'] = image_generations(tbl.text, model='dall-e-2')
|
|
395
|
+
"""
|
|
207
396
|
# TODO(aaron-siegel): Decompose CPU/GPU ops into separate functions
|
|
208
397
|
result = _retry(_openai_client().images.generate)(
|
|
209
398
|
prompt=prompt,
|
|
@@ -241,6 +430,31 @@ def _(size: Optional[str] = None) -> ts.ImageType:
|
|
|
241
430
|
|
|
242
431
|
@pxt.udf
|
|
243
432
|
def moderations(input: str, *, model: Optional[str] = None) -> dict:
|
|
433
|
+
"""
|
|
434
|
+
Classifies if text is potentially harmful.
|
|
435
|
+
|
|
436
|
+
Equivalent to the OpenAI `moderations` API endpoint.
|
|
437
|
+
For additional details, see: [https://platform.openai.com/docs/guides/moderation](https://platform.openai.com/docs/guides/moderation)
|
|
438
|
+
|
|
439
|
+
__Requirements:__
|
|
440
|
+
|
|
441
|
+
- `pip install openai`
|
|
442
|
+
|
|
443
|
+
Args:
|
|
444
|
+
input: Text to analyze with the moderations model.
|
|
445
|
+
model: The model to use for moderations.
|
|
446
|
+
|
|
447
|
+
For details on the other parameters, see: [https://platform.openai.com/docs/api-reference/moderations](https://platform.openai.com/docs/api-reference/moderations)
|
|
448
|
+
|
|
449
|
+
Returns:
|
|
450
|
+
Details of the moderations results.
|
|
451
|
+
|
|
452
|
+
Examples:
|
|
453
|
+
Add a computed column that applies the model `text-moderation-stable` to an existing
|
|
454
|
+
Pixeltable column `tbl.input` of the table `tbl`:
|
|
455
|
+
|
|
456
|
+
>>> tbl['moderations'] = moderations(tbl.text, model='text-moderation-stable')
|
|
457
|
+
"""
|
|
244
458
|
result = _retry(_openai_client().moderations.create)(input=input, model=_opt(model))
|
|
245
459
|
return result.dict()
|
|
246
460
|
|