pixeltable 0.3.14__py3-none-any.whl → 0.4.0rc1__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/__version__.py +2 -2
- pixeltable/catalog/catalog.py +292 -105
- pixeltable/catalog/column.py +10 -8
- pixeltable/catalog/dir.py +1 -2
- pixeltable/catalog/insertable_table.py +25 -20
- pixeltable/catalog/schema_object.py +3 -6
- pixeltable/catalog/table.py +245 -189
- pixeltable/catalog/table_version.py +319 -201
- pixeltable/catalog/table_version_handle.py +15 -2
- pixeltable/catalog/table_version_path.py +60 -21
- pixeltable/catalog/view.py +14 -5
- pixeltable/dataframe.py +11 -9
- pixeltable/env.py +2 -4
- pixeltable/exec/in_memory_data_node.py +1 -1
- pixeltable/exec/sql_node.py +20 -11
- pixeltable/exprs/column_property_ref.py +15 -6
- pixeltable/exprs/column_ref.py +32 -11
- pixeltable/exprs/comparison.py +1 -1
- pixeltable/exprs/row_builder.py +4 -6
- pixeltable/exprs/rowid_ref.py +8 -0
- pixeltable/exprs/similarity_expr.py +1 -0
- pixeltable/func/query_template_function.py +1 -1
- pixeltable/functions/gemini.py +166 -33
- pixeltable/functions/math.py +63 -0
- pixeltable/functions/string.py +212 -58
- pixeltable/globals.py +7 -4
- pixeltable/index/base.py +5 -0
- pixeltable/index/btree.py +5 -0
- pixeltable/index/embedding_index.py +5 -0
- pixeltable/io/external_store.py +8 -29
- pixeltable/io/label_studio.py +1 -1
- pixeltable/io/parquet.py +4 -4
- pixeltable/io/table_data_conduit.py +0 -31
- pixeltable/metadata/__init__.py +1 -1
- pixeltable/metadata/converters/convert_13.py +2 -2
- pixeltable/metadata/converters/convert_30.py +6 -11
- pixeltable/metadata/converters/convert_35.py +9 -0
- pixeltable/metadata/converters/util.py +3 -9
- pixeltable/metadata/notes.py +1 -0
- pixeltable/metadata/schema.py +5 -1
- pixeltable/plan.py +4 -4
- pixeltable/share/packager.py +207 -15
- pixeltable/share/publish.py +2 -2
- pixeltable/store.py +31 -13
- pixeltable/utils/dbms.py +1 -1
- {pixeltable-0.3.14.dist-info → pixeltable-0.4.0rc1.dist-info}/METADATA +1 -1
- {pixeltable-0.3.14.dist-info → pixeltable-0.4.0rc1.dist-info}/RECORD +50 -49
- {pixeltable-0.3.14.dist-info → pixeltable-0.4.0rc1.dist-info}/LICENSE +0 -0
- {pixeltable-0.3.14.dist-info → pixeltable-0.4.0rc1.dist-info}/WHEEL +0 -0
- {pixeltable-0.3.14.dist-info → pixeltable-0.4.0rc1.dist-info}/entry_points.txt +0 -0
pixeltable/functions/gemini.py
CHANGED
|
@@ -5,10 +5,16 @@ first `pip install google-genai` and configure your Gemini credentials, as descr
|
|
|
5
5
|
the [Working with Gemini](https://pixeltable.readme.io/docs/working-with-gemini) tutorial.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
+
import asyncio
|
|
9
|
+
import io
|
|
10
|
+
import tempfile
|
|
11
|
+
from pathlib import Path
|
|
8
12
|
from typing import TYPE_CHECKING, Optional
|
|
9
13
|
|
|
14
|
+
import PIL.Image
|
|
15
|
+
|
|
10
16
|
import pixeltable as pxt
|
|
11
|
-
from pixeltable import env
|
|
17
|
+
from pixeltable import env, exceptions as excs, exprs
|
|
12
18
|
|
|
13
19
|
if TYPE_CHECKING:
|
|
14
20
|
from google import genai
|
|
@@ -27,23 +33,11 @@ def _genai_client() -> 'genai.client.Client':
|
|
|
27
33
|
|
|
28
34
|
@pxt.udf(resource_pool='request-rate:gemini')
|
|
29
35
|
async def generate_content(
|
|
30
|
-
contents: str,
|
|
31
|
-
*,
|
|
32
|
-
model: str,
|
|
33
|
-
candidate_count: Optional[int] = None,
|
|
34
|
-
stop_sequences: Optional[list[str]] = None,
|
|
35
|
-
max_output_tokens: Optional[int] = None,
|
|
36
|
-
temperature: Optional[float] = None,
|
|
37
|
-
top_p: Optional[float] = None,
|
|
38
|
-
top_k: Optional[int] = None,
|
|
39
|
-
response_mime_type: Optional[str] = None,
|
|
40
|
-
response_schema: Optional[dict] = None,
|
|
41
|
-
presence_penalty: Optional[float] = None,
|
|
42
|
-
frequency_penalty: Optional[float] = None,
|
|
36
|
+
contents: str, *, model: str, config: Optional[dict] = None, tools: Optional[list[dict]] = None
|
|
43
37
|
) -> dict:
|
|
44
38
|
"""
|
|
45
39
|
Generate content from the specified model. For additional details, see:
|
|
46
|
-
<https://ai.google.dev/gemini-api/docs>
|
|
40
|
+
<https://ai.google.dev/gemini-api/docs/text-generation>
|
|
47
41
|
|
|
48
42
|
Request throttling:
|
|
49
43
|
Applies the rate limit set in the config (section `gemini`, key `rate_limit`). If no rate
|
|
@@ -56,38 +50,177 @@ async def generate_content(
|
|
|
56
50
|
Args:
|
|
57
51
|
contents: The input content to generate from.
|
|
58
52
|
model: The name of the model to use.
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
config: Configuration for generation, corresponding to keyword arguments of
|
|
54
|
+
`genai.types.GenerateContentConfig`. For details on the parameters, see:
|
|
55
|
+
<https://googleapis.github.io/python-genai/genai.html#module-genai.types>
|
|
56
|
+
tools: Optional list of Pixeltable tools to use. It is also possible to specify tools manually via the
|
|
57
|
+
`config.tools` parameter, but at most one of `config.tools` or `tools` may be used.
|
|
61
58
|
|
|
62
59
|
Returns:
|
|
63
60
|
A dictionary containing the response and other metadata.
|
|
64
61
|
|
|
65
62
|
Examples:
|
|
66
|
-
Add a computed column that applies the model `gemini-
|
|
63
|
+
Add a computed column that applies the model `gemini-2.0-flash`
|
|
67
64
|
to an existing Pixeltable column `tbl.prompt` of the table `tbl`:
|
|
68
65
|
|
|
69
|
-
>>> tbl.add_computed_column(response=generate_content(tbl.prompt, model='gemini-
|
|
66
|
+
>>> tbl.add_computed_column(response=generate_content(tbl.prompt, model='gemini-2.0-flash'))
|
|
70
67
|
"""
|
|
71
68
|
env.Env.get().require_package('google.genai')
|
|
72
69
|
from google.genai import types
|
|
73
70
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
response = await _genai_client().aio.models.generate_content(model=model, contents=contents, config=config)
|
|
71
|
+
config_: types.GenerateContentConfig
|
|
72
|
+
if config is None and tools is None:
|
|
73
|
+
config_ = None
|
|
74
|
+
else:
|
|
75
|
+
if config is None:
|
|
76
|
+
config_ = types.GenerateContentConfig()
|
|
77
|
+
else:
|
|
78
|
+
config_ = types.GenerateContentConfig(**config)
|
|
79
|
+
if tools is not None:
|
|
80
|
+
gemini_tools = [__convert_pxt_tool(tool) for tool in tools]
|
|
81
|
+
config_.tools = [types.Tool(function_declarations=gemini_tools)]
|
|
82
|
+
|
|
83
|
+
response = await _genai_client().aio.models.generate_content(model=model, contents=contents, config=config_)
|
|
88
84
|
return response.model_dump()
|
|
89
85
|
|
|
90
86
|
|
|
87
|
+
def __convert_pxt_tool(pxt_tool: dict) -> dict:
|
|
88
|
+
return {
|
|
89
|
+
'name': pxt_tool['name'],
|
|
90
|
+
'description': pxt_tool['description'],
|
|
91
|
+
'parameters': {
|
|
92
|
+
'type': 'object',
|
|
93
|
+
'properties': pxt_tool['parameters']['properties'],
|
|
94
|
+
'required': pxt_tool['required'],
|
|
95
|
+
},
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def invoke_tools(tools: pxt.func.Tools, response: exprs.Expr) -> exprs.InlineDict:
|
|
100
|
+
"""Converts an OpenAI response dict to Pixeltable tool invocation format and calls `tools._invoke()`."""
|
|
101
|
+
return tools._invoke(_gemini_response_to_pxt_tool_calls(response))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@pxt.udf
|
|
105
|
+
def _gemini_response_to_pxt_tool_calls(response: dict) -> Optional[dict]:
|
|
106
|
+
print(response)
|
|
107
|
+
pxt_tool_calls: dict[str, list[dict]] = {}
|
|
108
|
+
for part in response['candidates'][0]['content']['parts']:
|
|
109
|
+
tool_call = part.get('function_call')
|
|
110
|
+
if tool_call is not None:
|
|
111
|
+
tool_name = tool_call['name']
|
|
112
|
+
if tool_name not in pxt_tool_calls:
|
|
113
|
+
pxt_tool_calls[tool_name] = []
|
|
114
|
+
pxt_tool_calls[tool_name].append({'args': tool_call['args']})
|
|
115
|
+
if len(pxt_tool_calls) == 0:
|
|
116
|
+
return None
|
|
117
|
+
return pxt_tool_calls
|
|
118
|
+
|
|
119
|
+
|
|
91
120
|
@generate_content.resource_pool
|
|
92
121
|
def _(model: str) -> str:
|
|
93
122
|
return f'request-rate:gemini:{model}'
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@pxt.udf(resource_pool='request-rate:imagen')
|
|
126
|
+
async def generate_images(prompt: str, *, model: str, config: Optional[dict] = None) -> PIL.Image.Image:
|
|
127
|
+
"""
|
|
128
|
+
Generates images based on a text description and configuration. For additional details, see:
|
|
129
|
+
<https://ai.google.dev/gemini-api/docs/image-generation>
|
|
130
|
+
|
|
131
|
+
__Requirements:__
|
|
132
|
+
|
|
133
|
+
- `pip install google-genai`
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
prompt: A text description of the images to generate.
|
|
137
|
+
model: The model to use.
|
|
138
|
+
config: Configuration for generation, corresponding to keyword arguments of
|
|
139
|
+
`genai.types.GenerateImagesConfig`. For details on the parameters, see:
|
|
140
|
+
<https://googleapis.github.io/python-genai/genai.html#module-genai.types>
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
The generated image.
|
|
144
|
+
|
|
145
|
+
Examples:
|
|
146
|
+
Add a computed column that applies the model `imagen-3.0-generate-002`
|
|
147
|
+
to an existing Pixeltable column `tbl.prompt` of the table `tbl`:
|
|
148
|
+
|
|
149
|
+
>>> tbl.add_computed_column(response=generate_images(tbl.prompt, model='imagen-3.0-generate-002'))
|
|
150
|
+
"""
|
|
151
|
+
env.Env.get().require_package('google.genai')
|
|
152
|
+
from google.genai.types import GenerateImagesConfig
|
|
153
|
+
|
|
154
|
+
config_ = GenerateImagesConfig(**config) if config else None
|
|
155
|
+
response = await _genai_client().aio.models.generate_images(model=model, prompt=prompt, config=config_)
|
|
156
|
+
return response.generated_images[0].image._pil_image
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@generate_images.resource_pool
|
|
160
|
+
def _(model: str) -> str:
|
|
161
|
+
return f'request-rate:imagen:{model}'
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@pxt.udf(resource_pool='request-rate:veo')
|
|
165
|
+
async def generate_videos(
|
|
166
|
+
prompt: Optional[str] = None, image: Optional[PIL.Image.Image] = None, *, model: str, config: Optional[dict] = None
|
|
167
|
+
) -> pxt.Video:
|
|
168
|
+
"""
|
|
169
|
+
Generates videos based on a text description and configuration. For additional details, see:
|
|
170
|
+
<https://ai.google.dev/gemini-api/docs/video-generation>
|
|
171
|
+
|
|
172
|
+
__Requirements:__
|
|
173
|
+
|
|
174
|
+
- `pip install google-genai`
|
|
175
|
+
|
|
176
|
+
Args:
|
|
177
|
+
prompt: A text description of the videos to generate.
|
|
178
|
+
image: An optional image to use as the first frame of the video. At least one of `prompt` or `image` must be
|
|
179
|
+
provided. (It is ok to specify both.)
|
|
180
|
+
model: The model to use.
|
|
181
|
+
config: Configuration for generation, corresponding to keyword arguments of
|
|
182
|
+
`genai.types.GenerateVideosConfig`. For details on the parameters, see:
|
|
183
|
+
<https://googleapis.github.io/python-genai/genai.html#module-genai.types>
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
The generated video.
|
|
187
|
+
|
|
188
|
+
Examples:
|
|
189
|
+
Add a computed column that applies the model `veo-2.0-generate-001`
|
|
190
|
+
to an existing Pixeltable column `tbl.prompt` of the table `tbl`:
|
|
191
|
+
|
|
192
|
+
>>> tbl.add_computed_column(response=generate_videos(tbl.prompt, model='veo-2.0-generate-001'))
|
|
193
|
+
"""
|
|
194
|
+
env.Env.get().require_package('google.genai')
|
|
195
|
+
from google.genai import types
|
|
196
|
+
|
|
197
|
+
if prompt is None and image is None:
|
|
198
|
+
raise excs.Error('At least one of `prompt` or `image` must be provided.')
|
|
199
|
+
|
|
200
|
+
image_: Optional[types.Image] = None
|
|
201
|
+
if image is not None:
|
|
202
|
+
with io.BytesIO() as buffer:
|
|
203
|
+
image.save(buffer, format='jpeg')
|
|
204
|
+
image_ = types.Image(image_bytes=buffer.getvalue(), mime_type='image/jpeg')
|
|
205
|
+
|
|
206
|
+
config_ = types.GenerateVideosConfig(**config) if config else None
|
|
207
|
+
operation = await _genai_client().aio.models.generate_videos(
|
|
208
|
+
model=model, prompt=prompt, image=image_, config=config_
|
|
209
|
+
)
|
|
210
|
+
while not operation.done:
|
|
211
|
+
await asyncio.sleep(3)
|
|
212
|
+
operation = await _genai_client().aio.operations.get(operation)
|
|
213
|
+
|
|
214
|
+
video = operation.response.generated_videos[0]
|
|
215
|
+
|
|
216
|
+
video_bytes = await _genai_client().aio.files.download(file=video.video) # type: ignore[arg-type]
|
|
217
|
+
assert video_bytes is not None
|
|
218
|
+
|
|
219
|
+
_, output_filename = tempfile.mkstemp(suffix='.mp4', dir=str(env.Env.get().tmp_dir))
|
|
220
|
+
Path(output_filename).write_bytes(video_bytes)
|
|
221
|
+
return output_filename
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@generate_videos.resource_pool
|
|
225
|
+
def _(model: str) -> str:
|
|
226
|
+
return f'request-rate:veo:{model}'
|
pixeltable/functions/math.py
CHANGED
|
@@ -100,6 +100,69 @@ def _(self: sql.ColumnElement, digits: Optional[sql.ColumnElement] = None) -> sq
|
|
|
100
100
|
return sql.func.round(sql.cast(self, sql.Numeric), sql.cast(digits, sql.Integer))
|
|
101
101
|
|
|
102
102
|
|
|
103
|
+
@pxt.udf(is_method=True)
|
|
104
|
+
def pow(self: int, other: int) -> float:
|
|
105
|
+
"""
|
|
106
|
+
Raise `self` to the power of `other`.
|
|
107
|
+
|
|
108
|
+
Equivalent to Python [`self ** other`](https://docs.python.org/3/library/functions.html#pow).
|
|
109
|
+
"""
|
|
110
|
+
return self**other
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@pow.to_sql
|
|
114
|
+
def _(self: sql.ColumnElement, other: sql.ColumnElement) -> sql.ColumnElement:
|
|
115
|
+
return sql.func.pow(self, other)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@pxt.udf(is_method=True)
|
|
119
|
+
def bitwise_and(self: int, other: int) -> int:
|
|
120
|
+
"""
|
|
121
|
+
Bitwise AND of two integers.
|
|
122
|
+
|
|
123
|
+
Equivalent to Python
|
|
124
|
+
[`self & other`](https://docs.python.org/3/library/stdtypes.html#bitwise-operations-on-integer-types).
|
|
125
|
+
"""
|
|
126
|
+
return self & other
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@bitwise_and.to_sql
|
|
130
|
+
def _(self: sql.ColumnElement, other: sql.ColumnElement) -> sql.ColumnElement:
|
|
131
|
+
return self.bitwise_and(other)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@pxt.udf(is_method=True)
|
|
135
|
+
def bitwise_or(self: int, other: int) -> int:
|
|
136
|
+
"""
|
|
137
|
+
Bitwise OR of two integers.
|
|
138
|
+
|
|
139
|
+
Equivalent to Python
|
|
140
|
+
[`self | other`](https://docs.python.org/3/library/stdtypes.html#bitwise-operations-on-integer-types).
|
|
141
|
+
"""
|
|
142
|
+
return self | other
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@bitwise_or.to_sql
|
|
146
|
+
def _(self: sql.ColumnElement, other: sql.ColumnElement) -> sql.ColumnElement:
|
|
147
|
+
return self.bitwise_or(other)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@pxt.udf(is_method=True)
|
|
151
|
+
def bitwise_xor(self: int, other: int) -> int:
|
|
152
|
+
"""
|
|
153
|
+
Bitwise XOR of two integers.
|
|
154
|
+
|
|
155
|
+
Equivalent to Python
|
|
156
|
+
[`self ^ other`](https://docs.python.org/3/library/stdtypes.html#bitwise-operations-on-integer-types).
|
|
157
|
+
"""
|
|
158
|
+
return self ^ other
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@bitwise_xor.to_sql
|
|
162
|
+
def _(self: sql.ColumnElement, other: sql.ColumnElement) -> sql.ColumnElement:
|
|
163
|
+
return self.bitwise_xor(other)
|
|
164
|
+
|
|
165
|
+
|
|
103
166
|
__all__ = local_public_names(__name__)
|
|
104
167
|
|
|
105
168
|
|