pixeltable 0.3.1__py3-none-any.whl → 0.3.2__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/insertable_table.py +3 -3
- pixeltable/catalog/table.py +2 -2
- pixeltable/catalog/table_version.py +1 -1
- pixeltable/catalog/view.py +1 -1
- pixeltable/env.py +19 -2
- pixeltable/exec/expr_eval/evaluators.py +5 -10
- pixeltable/exec/expr_eval/expr_eval_node.py +5 -1
- pixeltable/exec/expr_eval/globals.py +3 -4
- pixeltable/exec/expr_eval/schedulers.py +21 -13
- pixeltable/exprs/row_builder.py +2 -2
- pixeltable/functions/anthropic.py +5 -3
- pixeltable/functions/openai.py +19 -7
- pixeltable/globals.py +1 -2
- pixeltable/io/hf_datasets.py +1 -1
- pixeltable/io/label_studio.py +5 -5
- pixeltable/io/parquet.py +1 -1
- pixeltable/metadata/__init__.py +2 -1
- pixeltable/type_system.py +71 -34
- pixeltable/utils/arrow.py +0 -5
- pixeltable/utils/console_output.py +41 -0
- pixeltable/utils/filecache.py +1 -1
- {pixeltable-0.3.1.dist-info → pixeltable-0.3.2.dist-info}/METADATA +2 -1
- {pixeltable-0.3.1.dist-info → pixeltable-0.3.2.dist-info}/RECORD +27 -26
- {pixeltable-0.3.1.dist-info → pixeltable-0.3.2.dist-info}/LICENSE +0 -0
- {pixeltable-0.3.1.dist-info → pixeltable-0.3.2.dist-info}/WHEEL +0 -0
- {pixeltable-0.3.1.dist-info → pixeltable-0.3.2.dist-info}/entry_points.txt +0 -0
pixeltable/__version__.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
# These version placeholders will be replaced during build.
|
|
2
|
-
__version__ = "0.3.
|
|
3
|
-
__version_tuple__ = (0, 3,
|
|
2
|
+
__version__ = "0.3.2"
|
|
3
|
+
__version_tuple__ = (0, 3, 2)
|
|
@@ -68,7 +68,7 @@ class InsertableTable(Table):
|
|
|
68
68
|
cat.tbls[tbl._id] = tbl
|
|
69
69
|
|
|
70
70
|
_logger.info(f'Created table `{name}`, id={tbl_version.id}')
|
|
71
|
-
|
|
71
|
+
Env.get().console_logger.info(f'Created table `{name}`.')
|
|
72
72
|
return tbl
|
|
73
73
|
|
|
74
74
|
def get_metadata(self) -> dict[str, Any]:
|
|
@@ -134,7 +134,7 @@ class InsertableTable(Table):
|
|
|
134
134
|
f'Inserted {status.num_rows} row{"" if status.num_rows == 1 else "s"} '
|
|
135
135
|
f'with {status.num_excs} error{"" if status.num_excs == 1 else "s"}{cols_with_excs_str}.'
|
|
136
136
|
)
|
|
137
|
-
|
|
137
|
+
Env.get().console_logger.info(msg)
|
|
138
138
|
_logger.info(f'InsertableTable {self._name}: {msg}')
|
|
139
139
|
FileCache.get().emit_eviction_warnings()
|
|
140
140
|
return status
|
|
@@ -164,7 +164,7 @@ class InsertableTable(Table):
|
|
|
164
164
|
row[col_name] = checked_val
|
|
165
165
|
except TypeError as e:
|
|
166
166
|
msg = str(e)
|
|
167
|
-
raise excs.Error(f'Error in column {col.name}: {msg[0].lower() + msg[1:]}\nRow: {row}')
|
|
167
|
+
raise excs.Error(f'Error in column {col.name}: {msg[0].lower() + msg[1:]}\nRow: {row}') from e
|
|
168
168
|
|
|
169
169
|
def delete(self, where: Optional['pxt.exprs.Expr'] = None) -> UpdateStatus:
|
|
170
170
|
"""Delete rows in this table.
|
pixeltable/catalog/table.py
CHANGED
|
@@ -1345,7 +1345,7 @@ class Table(SchemaObject):
|
|
|
1345
1345
|
raise excs.Error(f'Table `{self._name}` already has an external store with that name: {store.name}')
|
|
1346
1346
|
_logger.info(f'Linking external store `{store.name}` to table `{self._name}`')
|
|
1347
1347
|
self._tbl_version.link_external_store(store)
|
|
1348
|
-
|
|
1348
|
+
env.Env.get().console_logger.info(f'Linked external store `{store.name}` to table `{self._name}`.')
|
|
1349
1349
|
|
|
1350
1350
|
def unlink_external_stores(
|
|
1351
1351
|
self,
|
|
@@ -1381,7 +1381,7 @@ class Table(SchemaObject):
|
|
|
1381
1381
|
|
|
1382
1382
|
for store in stores:
|
|
1383
1383
|
self._tbl_version.unlink_external_store(store, delete_external_data=delete_external_data)
|
|
1384
|
-
|
|
1384
|
+
env.Env.get().console_logger.info(f'Unlinked external store from table `{self._name}`: {store}')
|
|
1385
1385
|
|
|
1386
1386
|
def sync(
|
|
1387
1387
|
self,
|
|
@@ -532,7 +532,7 @@ class TableVersion:
|
|
|
532
532
|
f'Added {status.num_rows} column value{"" if status.num_rows == 1 else "s"} '
|
|
533
533
|
f'with {status.num_excs} error{"" if status.num_excs == 1 else "s"}.'
|
|
534
534
|
)
|
|
535
|
-
|
|
535
|
+
Env.get().console_logger.info(msg)
|
|
536
536
|
_logger.info(f'Columns {[col.name for col in cols]}: {msg}')
|
|
537
537
|
return status
|
|
538
538
|
|
pixeltable/catalog/view.py
CHANGED
|
@@ -156,7 +156,7 @@ class View(Table):
|
|
|
156
156
|
plan, num_values_per_row = Planner.create_view_load_plan(view._tbl_version_path)
|
|
157
157
|
num_rows, num_excs, cols_with_excs = tbl_version.store_tbl.insert_rows(
|
|
158
158
|
plan, session.connection(), v_min=tbl_version.version)
|
|
159
|
-
|
|
159
|
+
Env.get().console_logger.info(f'Created view `{name}` with {num_rows} rows, {num_excs} exceptions.')
|
|
160
160
|
|
|
161
161
|
session.commit()
|
|
162
162
|
cat = Catalog.get()
|
pixeltable/env.py
CHANGED
|
@@ -18,7 +18,8 @@ import uuid
|
|
|
18
18
|
import warnings
|
|
19
19
|
from dataclasses import dataclass, field
|
|
20
20
|
from pathlib import Path
|
|
21
|
-
from
|
|
21
|
+
from sys import stdout
|
|
22
|
+
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar
|
|
22
23
|
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
|
|
23
24
|
|
|
24
25
|
import pixeltable_pgserver
|
|
@@ -28,6 +29,7 @@ from tqdm import TqdmWarning
|
|
|
28
29
|
|
|
29
30
|
import pixeltable.exceptions as excs
|
|
30
31
|
from pixeltable import metadata
|
|
32
|
+
from pixeltable.utils.console_output import ConsoleLogger, ConsoleMessageFilter, ConsoleOutputHandler, map_level
|
|
31
33
|
from pixeltable.utils.http_server import make_server
|
|
32
34
|
|
|
33
35
|
if TYPE_CHECKING:
|
|
@@ -67,6 +69,7 @@ class Env:
|
|
|
67
69
|
_httpd: Optional[http.server.HTTPServer]
|
|
68
70
|
_http_address: Optional[str]
|
|
69
71
|
_logger: logging.Logger
|
|
72
|
+
_console_logger: ConsoleLogger
|
|
70
73
|
_default_log_level: int
|
|
71
74
|
_logfilename: Optional[str]
|
|
72
75
|
_log_to_stdout: bool
|
|
@@ -92,6 +95,8 @@ class Env:
|
|
|
92
95
|
cls._instance = env
|
|
93
96
|
|
|
94
97
|
def __init__(self):
|
|
98
|
+
assert self._instance is None, 'Env is a singleton; use Env.get() to access the instance'
|
|
99
|
+
|
|
95
100
|
self._home = None
|
|
96
101
|
self._media_dir = None # computed media files
|
|
97
102
|
self._file_cache_dir = None # cached media files with external URL
|
|
@@ -231,6 +236,10 @@ class Env:
|
|
|
231
236
|
else:
|
|
232
237
|
return False
|
|
233
238
|
|
|
239
|
+
@property
|
|
240
|
+
def console_logger(self) -> ConsoleLogger:
|
|
241
|
+
return self._console_logger
|
|
242
|
+
|
|
234
243
|
def _set_up(self, echo: bool = False, reinit_db: bool = False) -> None:
|
|
235
244
|
if self._initialized:
|
|
236
245
|
return
|
|
@@ -288,6 +297,14 @@ class Env:
|
|
|
288
297
|
warnings.simplefilter('ignore', category=UserWarning)
|
|
289
298
|
warnings.simplefilter('ignore', category=FutureWarning)
|
|
290
299
|
|
|
300
|
+
# Set verbose level for user visible console messages
|
|
301
|
+
verbosity = map_level(self._config.get_int_value('verbosity'))
|
|
302
|
+
stdout_handler = ConsoleOutputHandler(stream=stdout)
|
|
303
|
+
stdout_handler.setLevel(verbosity)
|
|
304
|
+
stdout_handler.addFilter(ConsoleMessageFilter())
|
|
305
|
+
self._logger.addHandler(stdout_handler)
|
|
306
|
+
self._console_logger = ConsoleLogger(self._logger)
|
|
307
|
+
|
|
291
308
|
# configure _logger to log to a file
|
|
292
309
|
self._logfilename = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') + '.log'
|
|
293
310
|
fh = logging.FileHandler(self._log_dir / self._logfilename, mode='w')
|
|
@@ -361,7 +378,7 @@ class Env:
|
|
|
361
378
|
schema.base_metadata.create_all(self._sa_engine)
|
|
362
379
|
metadata.create_system_info(self._sa_engine)
|
|
363
380
|
|
|
364
|
-
|
|
381
|
+
self.console_logger.info(f'Connected to Pixeltable database at: {self.db_url}')
|
|
365
382
|
|
|
366
383
|
# we now have a home directory and db; start other services
|
|
367
384
|
self._set_up_runtime()
|
|
@@ -32,8 +32,7 @@ class DefaultExprEvaluator(Evaluator):
|
|
|
32
32
|
def schedule(self, rows: list[exprs.DataRow], slot_idx: int) -> None:
|
|
33
33
|
assert self.e.slot_idx >= 0
|
|
34
34
|
task = asyncio.create_task(self.eval(rows))
|
|
35
|
-
self.dispatcher.
|
|
36
|
-
task.add_done_callback(self.dispatcher.done_cb)
|
|
35
|
+
self.dispatcher.register_task(task)
|
|
37
36
|
|
|
38
37
|
async def eval(self, rows: list[exprs.DataRow]) -> None:
|
|
39
38
|
rows_with_excs: set[int] = set() # records idxs into rows
|
|
@@ -134,8 +133,7 @@ class FnCallEvaluator(Evaluator):
|
|
|
134
133
|
scheduler.submit(batched_call_args)
|
|
135
134
|
else:
|
|
136
135
|
task = asyncio.create_task(self.eval_batch(batched_call_args))
|
|
137
|
-
self.dispatcher.
|
|
138
|
-
task.add_done_callback(self.dispatcher.done_cb)
|
|
136
|
+
self.dispatcher.register_task(task)
|
|
139
137
|
|
|
140
138
|
elif self.fn.is_async:
|
|
141
139
|
if self.fn_call.resource_pool is not None:
|
|
@@ -147,14 +145,12 @@ class FnCallEvaluator(Evaluator):
|
|
|
147
145
|
# create one task per call
|
|
148
146
|
for item in rows_call_args:
|
|
149
147
|
task = asyncio.create_task(self.eval_async(item))
|
|
150
|
-
self.dispatcher.
|
|
151
|
-
task.add_done_callback(self.dispatcher.done_cb)
|
|
148
|
+
self.dispatcher.register_task(task)
|
|
152
149
|
|
|
153
150
|
else:
|
|
154
151
|
# create a single task for all rows
|
|
155
152
|
task = asyncio.create_task(self.eval(rows_call_args))
|
|
156
|
-
self.dispatcher.
|
|
157
|
-
task.add_done_callback(self.dispatcher.done_cb)
|
|
153
|
+
self.dispatcher.register_task(task)
|
|
158
154
|
|
|
159
155
|
def _queued_call_args_iter(self) -> Iterator[FnCallArgs]:
|
|
160
156
|
while not self.call_args_queue.empty():
|
|
@@ -241,5 +237,4 @@ class FnCallEvaluator(Evaluator):
|
|
|
241
237
|
return
|
|
242
238
|
batched_call_args = self._create_batch_call_args(list(self._queued_call_args_iter()))
|
|
243
239
|
task = asyncio.create_task(self.eval_batch(batched_call_args))
|
|
244
|
-
self.dispatcher.
|
|
245
|
-
task.add_done_callback(self.dispatcher.done_cb)
|
|
240
|
+
self.dispatcher.register_task(task)
|
|
@@ -391,7 +391,11 @@ class ExprEvalNode(ExecNode):
|
|
|
391
391
|
_logger.debug(f'Scheduling {len(ready_rows)} rows for slot {slot_idx}')
|
|
392
392
|
self.slot_evaluators[slot_idx].schedule(ready_rows, slot_idx)
|
|
393
393
|
|
|
394
|
-
def
|
|
394
|
+
def register_task(self, t: asyncio.Task) -> None:
|
|
395
|
+
self.tasks.add(t)
|
|
396
|
+
t.add_done_callback(self._done_cb)
|
|
397
|
+
|
|
398
|
+
def _done_cb(self, t: asyncio.Task) -> None:
|
|
395
399
|
self.tasks.discard(t)
|
|
396
400
|
# end the main loop if we had an unhandled exception
|
|
397
401
|
try:
|
|
@@ -59,11 +59,10 @@ class Dispatcher(Protocol):
|
|
|
59
59
|
"""
|
|
60
60
|
Row dispatcher used by Evaluators/Schedulers for post-processing after slot materialization and for task management.
|
|
61
61
|
|
|
62
|
-
Task management: all tasks need to be
|
|
62
|
+
Task management: all tasks need to be registered via register_task()
|
|
63
63
|
Exceptions: evaluators/schedulers need to check exc_event prior to starting long-running (non-interruptible)
|
|
64
64
|
computations
|
|
65
65
|
"""
|
|
66
|
-
tasks: set[asyncio.Task]
|
|
67
66
|
row_builder: exprs.RowBuilder
|
|
68
67
|
exc_event: asyncio.Event
|
|
69
68
|
schedulers: dict[str, Scheduler] # key: resource pool id
|
|
@@ -76,8 +75,8 @@ class Dispatcher(Protocol):
|
|
|
76
75
|
"""Propagates exception in slot_with_exc to all dependent slots and dispatches the rest; does not block"""
|
|
77
76
|
...
|
|
78
77
|
|
|
79
|
-
def
|
|
80
|
-
"""
|
|
78
|
+
def register_task(self, f: asyncio.Task) -> None:
|
|
79
|
+
"""Register task with dispatcher for subsequent cleanup; does not block"""
|
|
81
80
|
...
|
|
82
81
|
|
|
83
82
|
|
|
@@ -62,8 +62,7 @@ class RateLimitsScheduler(Scheduler):
|
|
|
62
62
|
self.queue = asyncio.PriorityQueue()
|
|
63
63
|
self.dispatcher = dispatcher
|
|
64
64
|
self.loop_task = asyncio.create_task(self._main_loop())
|
|
65
|
-
self.dispatcher.
|
|
66
|
-
self.loop_task.add_done_callback(self.dispatcher.done_cb)
|
|
65
|
+
self.dispatcher.register_task(self.loop_task)
|
|
67
66
|
self.pool_info = None # initialized in _main_loop by the first request
|
|
68
67
|
self.est_usage = {}
|
|
69
68
|
self.num_in_flight = 0
|
|
@@ -79,6 +78,19 @@ class RateLimitsScheduler(Scheduler):
|
|
|
79
78
|
def submit(self, item: FnCallArgs) -> None:
|
|
80
79
|
self.queue.put_nowait(self.QueueItem(item, 0))
|
|
81
80
|
|
|
81
|
+
def _set_pool_info(self) -> None:
|
|
82
|
+
"""Initialize pool_info with the RateLimitsInfo for the resource pool, if available"""
|
|
83
|
+
if self.pool_info is not None:
|
|
84
|
+
return
|
|
85
|
+
self.pool_info = env.Env.get().get_resource_pool_info(self.resource_pool, None)
|
|
86
|
+
if self.pool_info is None:
|
|
87
|
+
return
|
|
88
|
+
assert isinstance(self.pool_info, env.RateLimitsInfo)
|
|
89
|
+
assert hasattr(self.pool_info, 'get_request_resources')
|
|
90
|
+
sig = inspect.signature(self.pool_info.get_request_resources)
|
|
91
|
+
self.get_request_resources_param_names = [p.name for p in sig.parameters.values()]
|
|
92
|
+
self.est_usage = {r: 0 for r in self._resources}
|
|
93
|
+
|
|
82
94
|
async def _main_loop(self) -> None:
|
|
83
95
|
item: Optional[RateLimitsScheduler.QueueItem] = None
|
|
84
96
|
while True:
|
|
@@ -95,15 +107,7 @@ class RateLimitsScheduler(Scheduler):
|
|
|
95
107
|
item = None
|
|
96
108
|
# if this was the first request, it created the pool_info
|
|
97
109
|
if self.pool_info is None:
|
|
98
|
-
self.
|
|
99
|
-
if self.pool_info is None:
|
|
100
|
-
# we still don't have rate limits, wait for the next request
|
|
101
|
-
continue
|
|
102
|
-
assert isinstance(self.pool_info, env.RateLimitsInfo)
|
|
103
|
-
assert hasattr(self.pool_info, 'get_request_resources')
|
|
104
|
-
sig = inspect.signature(self.pool_info.get_request_resources)
|
|
105
|
-
self.get_request_resources_param_names = [p.name for p in sig.parameters.values()]
|
|
106
|
-
self.est_usage = {r: 0 for r in self._resources}
|
|
110
|
+
self._set_pool_info()
|
|
107
111
|
continue
|
|
108
112
|
|
|
109
113
|
# check rate limits
|
|
@@ -149,8 +153,7 @@ class RateLimitsScheduler(Scheduler):
|
|
|
149
153
|
_logger.debug(f'creating task for {self.resource_pool}')
|
|
150
154
|
self.num_in_flight += 1
|
|
151
155
|
task = asyncio.create_task(self._exec(item.request, item.num_retries, is_task=True))
|
|
152
|
-
self.dispatcher.
|
|
153
|
-
task.add_done_callback(self.dispatcher.done_cb)
|
|
156
|
+
self.dispatcher.register_task(task)
|
|
154
157
|
item = None
|
|
155
158
|
|
|
156
159
|
@property
|
|
@@ -206,10 +209,15 @@ class RateLimitsScheduler(Scheduler):
|
|
|
206
209
|
|
|
207
210
|
self.dispatcher.dispatch(request.rows)
|
|
208
211
|
except Exception as exc:
|
|
212
|
+
_logger.debug(f'scheduler {self.resource_pool}: exception in slot {request.fn_call.slot_idx}: {exc}')
|
|
213
|
+
if self.pool_info is None:
|
|
214
|
+
# our pool info should be available at this point
|
|
215
|
+
self._set_pool_info()
|
|
209
216
|
if num_retries < self.MAX_RETRIES and self.pool_info is not None:
|
|
210
217
|
retry_delay = self.pool_info.get_retry_delay(exc)
|
|
211
218
|
if retry_delay is not None:
|
|
212
219
|
self.total_retried += 1
|
|
220
|
+
_logger.debug(f'scheduler {self.resource_pool}: retrying in {retry_delay} seconds')
|
|
213
221
|
await asyncio.sleep(retry_delay)
|
|
214
222
|
self.queue.put_nowait(self.QueueItem(request, num_retries + 1))
|
|
215
223
|
return
|
pixeltable/exprs/row_builder.py
CHANGED
|
@@ -8,13 +8,13 @@ from uuid import UUID
|
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
import sqlalchemy as sql
|
|
11
|
-
|
|
12
11
|
import pixeltable.catalog as catalog
|
|
13
12
|
import pixeltable.exceptions as excs
|
|
14
13
|
import pixeltable.func as func
|
|
15
14
|
import pixeltable.utils as utils
|
|
16
15
|
from pixeltable.utils.media_store import MediaStore
|
|
17
16
|
from .data_row import DataRow
|
|
17
|
+
from pixeltable.env import Env
|
|
18
18
|
from .expr import Expr
|
|
19
19
|
from .expr_set import ExprSet
|
|
20
20
|
|
|
@@ -32,7 +32,7 @@ class ExecProfile:
|
|
|
32
32
|
per_call_time = self.eval_time[i] / self.eval_count[i]
|
|
33
33
|
calls_per_row = self.eval_count[i] / num_rows
|
|
34
34
|
multiple_str = f'({calls_per_row}x)' if calls_per_row > 1 else ''
|
|
35
|
-
|
|
35
|
+
Env.get().console_logger.info(f'{self.row_builder.unique_exprs[i]}: {utils.print_perf_counter_delta(per_call_time)} {multiple_str}')
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
@dataclass
|
|
@@ -137,6 +137,11 @@ async def messages(
|
|
|
137
137
|
if not tool_choice['parallel_tool_calls']:
|
|
138
138
|
tool_choice_['disable_parallel_tool_use'] = True
|
|
139
139
|
|
|
140
|
+
# make sure the pool info exists prior to making the request
|
|
141
|
+
resource_pool_id = f'rate-limits:anthropic:{model}'
|
|
142
|
+
rate_limits_info = env.Env.get().get_resource_pool_info(resource_pool_id, AnthropicRateLimitsInfo)
|
|
143
|
+
assert isinstance(rate_limits_info, env.RateLimitsInfo)
|
|
144
|
+
|
|
140
145
|
# TODO: timeouts should be set system-wide and be user-configurable
|
|
141
146
|
from anthropic.types import MessageParam
|
|
142
147
|
|
|
@@ -178,9 +183,6 @@ async def messages(
|
|
|
178
183
|
if retry_after_str is not None:
|
|
179
184
|
_logger.debug(f'retry-after: {retry_after_str}')
|
|
180
185
|
|
|
181
|
-
resource_pool_id = f'rate-limits:anthropic:{model}'
|
|
182
|
-
rate_limits_info = env.Env.get().get_resource_pool_info(resource_pool_id, AnthropicRateLimitsInfo)
|
|
183
|
-
assert isinstance(rate_limits_info, env.RateLimitsInfo)
|
|
184
186
|
rate_limits_info.record(
|
|
185
187
|
requests=(requests_limit, requests_remaining, requests_reset),
|
|
186
188
|
input_tokens=(input_tokens_limit, input_tokens_remaining, input_tokens_reset),
|
pixeltable/functions/openai.py
CHANGED
|
@@ -113,7 +113,17 @@ class OpenAIRateLimitsInfo(env.RateLimitsInfo):
|
|
|
113
113
|
super().__init__(get_request_resources)
|
|
114
114
|
import openai
|
|
115
115
|
self.retryable_errors = (
|
|
116
|
-
|
|
116
|
+
# ConnectionError: we occasionally see this error when the AsyncConnectionPool is trying to close
|
|
117
|
+
# expired connections
|
|
118
|
+
# (AsyncConnectionPool._close_expired_connections() fails with ConnectionError when executing
|
|
119
|
+
# 'await connection.aclose()', which is potentially a bug in AsyncConnectionPool)
|
|
120
|
+
openai.APIConnectionError,
|
|
121
|
+
|
|
122
|
+
# the following errors are retryable according to OpenAI's API documentation
|
|
123
|
+
openai.RateLimitError,
|
|
124
|
+
openai.APITimeoutError,
|
|
125
|
+
openai.UnprocessableEntityError,
|
|
126
|
+
openai.InternalServerError,
|
|
117
127
|
)
|
|
118
128
|
|
|
119
129
|
def get_retry_delay(self, exc: Exception) -> Optional[float]:
|
|
@@ -400,6 +410,11 @@ async def chat_completions(
|
|
|
400
410
|
if tool_choice is not None and not tool_choice['parallel_tool_calls']:
|
|
401
411
|
extra_body = {'parallel_tool_calls': False}
|
|
402
412
|
|
|
413
|
+
# make sure the pool info exists prior to making the request
|
|
414
|
+
resource_pool = _resource_pool(model)
|
|
415
|
+
rate_limits_info = env.Env.get().get_resource_pool_info(
|
|
416
|
+
resource_pool, lambda: OpenAIRateLimitsInfo(_chat_completions_get_request_resources))
|
|
417
|
+
|
|
403
418
|
# cast(Any, ...): avoid mypy errors
|
|
404
419
|
result = await _async_openai_client().chat.completions.with_raw_response.create(
|
|
405
420
|
messages=messages,
|
|
@@ -423,10 +438,7 @@ async def chat_completions(
|
|
|
423
438
|
extra_body=extra_body,
|
|
424
439
|
)
|
|
425
440
|
|
|
426
|
-
resource_pool = _resource_pool(model)
|
|
427
441
|
requests_info, tokens_info = _get_header_info(result.headers)
|
|
428
|
-
rate_limits_info = env.Env.get().get_resource_pool_info(resource_pool, lambda: OpenAIRateLimitsInfo(
|
|
429
|
-
_chat_completions_get_request_resources))
|
|
430
442
|
rate_limits_info.record(requests=requests_info, tokens=tokens_info)
|
|
431
443
|
|
|
432
444
|
return json.loads(result.text)
|
|
@@ -523,13 +535,13 @@ async def embeddings(
|
|
|
523
535
|
>>> tbl['embed'] = embeddings(tbl.text, model='text-embedding-3-small')
|
|
524
536
|
"""
|
|
525
537
|
_logger.debug(f'embeddings: batch_size={len(input)}')
|
|
538
|
+
resource_pool = _resource_pool(model)
|
|
539
|
+
rate_limits_info = env.Env.get().get_resource_pool_info(
|
|
540
|
+
resource_pool, lambda: OpenAIRateLimitsInfo(_embeddings_get_request_resources))
|
|
526
541
|
result = await _async_openai_client().embeddings.with_raw_response.create(
|
|
527
542
|
input=input, model=model, dimensions=_opt(dimensions), user=_opt(user), encoding_format='float'
|
|
528
543
|
)
|
|
529
|
-
resource_pool = _resource_pool(model)
|
|
530
544
|
requests_info, tokens_info = _get_header_info(result.headers)
|
|
531
|
-
rate_limits_info = env.Env.get().get_resource_pool_info(
|
|
532
|
-
resource_pool, lambda: OpenAIRateLimitsInfo(_embeddings_get_request_resources))
|
|
533
545
|
rate_limits_info.record(requests=requests_info, tokens=tokens_info)
|
|
534
546
|
return [np.array(data['embedding'], dtype=np.float64) for data in json.loads(result.content)['data']]
|
|
535
547
|
|
pixeltable/globals.py
CHANGED
|
@@ -606,8 +606,7 @@ def create_dir(path_str: str, if_exists: Literal['error', 'ignore', 'replace', '
|
|
|
606
606
|
dir = catalog.Dir(dir_record.id, parent._id, path.name)
|
|
607
607
|
cat.paths[path] = dir
|
|
608
608
|
session.commit()
|
|
609
|
-
|
|
610
|
-
print(f'Created directory `{path_str}`.')
|
|
609
|
+
Env.get().console_logger.info(f'Created directory `{path_str}`.')
|
|
611
610
|
return dir
|
|
612
611
|
|
|
613
612
|
def drop_dir(path_str: str, force: bool = False, if_not_exists: Literal['error', 'ignore'] = 'error') -> None:
|
pixeltable/io/hf_datasets.py
CHANGED
|
@@ -13,7 +13,7 @@ from pixeltable import exceptions as excs
|
|
|
13
13
|
if typing.TYPE_CHECKING:
|
|
14
14
|
import datasets # type: ignore[import-untyped]
|
|
15
15
|
|
|
16
|
-
_logger = logging.getLogger(
|
|
16
|
+
_logger = logging.getLogger('pixeltable')
|
|
17
17
|
|
|
18
18
|
# use 100MB as the batch size limit for loading a huggingface dataset into pixeltable.
|
|
19
19
|
# The primary goal is to bound memory use, regardless of dataset size.
|
pixeltable/io/label_studio.py
CHANGED
|
@@ -230,7 +230,7 @@ class LabelStudioProject(Project):
|
|
|
230
230
|
self.project.create_predictions(predictions)
|
|
231
231
|
tasks_created += 1
|
|
232
232
|
|
|
233
|
-
|
|
233
|
+
env.Env.get().console_logger.info(f'Created {tasks_created} new task(s) in {self}.')
|
|
234
234
|
|
|
235
235
|
sync_status = SyncStatus(external_rows_created=tasks_created)
|
|
236
236
|
|
|
@@ -330,7 +330,7 @@ class LabelStudioProject(Project):
|
|
|
330
330
|
if len(page) > 0:
|
|
331
331
|
self.project.import_tasks(page)
|
|
332
332
|
|
|
333
|
-
|
|
333
|
+
env.Env.get().console_logger.info(f'Created {tasks_created} new task(s) and updated {tasks_updated} existing task(s) in {self}.')
|
|
334
334
|
|
|
335
335
|
sync_status = SyncStatus(external_rows_created=tasks_created, external_rows_updated=tasks_updated)
|
|
336
336
|
|
|
@@ -363,7 +363,7 @@ class LabelStudioProject(Project):
|
|
|
363
363
|
|
|
364
364
|
if len(tasks_to_delete) > 0:
|
|
365
365
|
self.project.delete_tasks(tasks_to_delete)
|
|
366
|
-
|
|
366
|
+
env.Env.get().console_logger.info(f'Deleted {len(tasks_to_delete)} tasks(s) in {self} that are no longer present in Pixeltable.')
|
|
367
367
|
|
|
368
368
|
# Remove them from the `existing_tasks` dict so that future updates are applied correctly
|
|
369
369
|
for rowid in deleted_rowids:
|
|
@@ -406,7 +406,7 @@ class LabelStudioProject(Project):
|
|
|
406
406
|
assert ancestor._base is not None
|
|
407
407
|
ancestor = ancestor._base
|
|
408
408
|
update_status = ancestor.batch_update(updates)
|
|
409
|
-
|
|
409
|
+
env.Env.get().console_logger.info(f'Updated annotation(s) from {len(updates)} task(s) in {self}.')
|
|
410
410
|
return SyncStatus(pxt_rows_updated=update_status.num_rows, num_excs=update_status.num_excs)
|
|
411
411
|
else:
|
|
412
412
|
return SyncStatus.empty()
|
|
@@ -529,7 +529,7 @@ class LabelStudioProject(Project):
|
|
|
529
529
|
"""
|
|
530
530
|
title = self.project_title
|
|
531
531
|
_label_studio_client().delete_project(self.project_id)
|
|
532
|
-
|
|
532
|
+
env.Env.get().console_logger.info(f'Deleted Label Studio project: {title}')
|
|
533
533
|
|
|
534
534
|
def __eq__(self, other) -> bool:
|
|
535
535
|
return isinstance(other, LabelStudioProject) and self.project_id == other.project_id
|
pixeltable/io/parquet.py
CHANGED
|
@@ -23,7 +23,7 @@ if typing.TYPE_CHECKING:
|
|
|
23
23
|
import pyarrow as pa
|
|
24
24
|
import pixeltable as pxt
|
|
25
25
|
|
|
26
|
-
_logger = logging.getLogger(
|
|
26
|
+
_logger = logging.getLogger('pixeltable')
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def _write_batch(value_batch: dict[str, deque], schema: pa.Schema, output_path: Path) -> None:
|
pixeltable/metadata/__init__.py
CHANGED
|
@@ -47,7 +47,8 @@ def upgrade_md(engine: sql.engine.Engine) -> None:
|
|
|
47
47
|
while md_version < VERSION:
|
|
48
48
|
if md_version not in converter_cbs:
|
|
49
49
|
raise RuntimeError(f'No metadata converter for version {md_version}')
|
|
50
|
-
|
|
50
|
+
from pixeltable.env import Env
|
|
51
|
+
Env.get().console_logger.info(f'Converting metadata from version {md_version} to {md_version + 1}')
|
|
51
52
|
converter_cbs[md_version](engine)
|
|
52
53
|
md_version += 1
|
|
53
54
|
# update system info
|
pixeltable/type_system.py
CHANGED
|
@@ -793,12 +793,19 @@ class JsonType(ColumnType):
|
|
|
793
793
|
|
|
794
794
|
|
|
795
795
|
class ArrayType(ColumnType):
|
|
796
|
-
|
|
796
|
+
|
|
797
|
+
shape: Optional[tuple[Optional[int], ...]]
|
|
798
|
+
pxt_dtype: Optional[ColumnType]
|
|
799
|
+
dtype: Optional[ColumnType.Type]
|
|
800
|
+
|
|
801
|
+
def __init__(self, shape: Optional[tuple[Optional[int], ...]] = None, dtype: Optional[ColumnType] = None, nullable: bool = False):
|
|
797
802
|
super().__init__(self.Type.ARRAY, nullable=nullable)
|
|
803
|
+
assert shape is None or dtype is not None, (shape, dtype) # cannot specify a shape without a dtype
|
|
804
|
+
assert dtype is None or dtype.is_int_type() or dtype.is_float_type() or dtype.is_bool_type() or dtype.is_string_type()
|
|
805
|
+
|
|
798
806
|
self.shape = shape
|
|
799
|
-
|
|
800
|
-
self.
|
|
801
|
-
self.dtype = dtype._type
|
|
807
|
+
self.pxt_dtype = dtype # we need this for copy() and __str__()
|
|
808
|
+
self.dtype = None if dtype is None else dtype._type
|
|
802
809
|
|
|
803
810
|
def copy(self, nullable: bool) -> ColumnType:
|
|
804
811
|
return ArrayType(self.shape, self.pxt_dtype, nullable=nullable)
|
|
@@ -812,28 +819,38 @@ class ArrayType(ColumnType):
|
|
|
812
819
|
def supertype(self, other: ColumnType) -> Optional[ArrayType]:
|
|
813
820
|
if not isinstance(other, ArrayType):
|
|
814
821
|
return None
|
|
822
|
+
super_dtype = self.Type.supertype(self.dtype, other.dtype, self.common_supertypes)
|
|
823
|
+
if super_dtype is None:
|
|
824
|
+
# if the dtypes are incompatible, then the supertype is a fully general array
|
|
825
|
+
return ArrayType(nullable=(self.nullable or other.nullable))
|
|
826
|
+
super_shape: Optional[tuple[Optional[int], ...]]
|
|
815
827
|
if len(self.shape) != len(other.shape):
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
shape = [n1 if n1 == n2 else None for n1, n2 in zip(self.shape, other.shape)]
|
|
821
|
-
return ArrayType(tuple(shape), self.make_type(base_type), nullable=(self.nullable or other.nullable))
|
|
828
|
+
super_shape = None
|
|
829
|
+
else:
|
|
830
|
+
super_shape = tuple(n1 if n1 == n2 else None for n1, n2 in zip(self.shape, other.shape))
|
|
831
|
+
return ArrayType(super_shape, self.make_type(super_dtype), nullable=(self.nullable or other.nullable))
|
|
822
832
|
|
|
823
833
|
def _as_dict(self) -> dict:
|
|
824
834
|
result = super()._as_dict()
|
|
825
|
-
|
|
835
|
+
shape_as_list = None if self.shape is None else list(self.shape)
|
|
836
|
+
dtype_value = None if self.dtype is None else self.dtype.value
|
|
837
|
+
result.update(shape=shape_as_list, dtype=dtype_value)
|
|
826
838
|
return result
|
|
827
839
|
|
|
828
840
|
def _to_base_str(self) -> str:
|
|
841
|
+
if self.shape is None and self.dtype is None:
|
|
842
|
+
return 'Array'
|
|
843
|
+
if self.shape is None:
|
|
844
|
+
return f'Array[{self.pxt_dtype}]'
|
|
845
|
+
assert self.dtype is not None
|
|
829
846
|
return f'Array[{self.shape}, {self.pxt_dtype}]'
|
|
830
847
|
|
|
831
848
|
@classmethod
|
|
832
849
|
def _from_dict(cls, d: dict) -> ColumnType:
|
|
833
850
|
assert 'shape' in d
|
|
834
851
|
assert 'dtype' in d
|
|
835
|
-
shape = tuple(d['shape'])
|
|
836
|
-
dtype = cls.make_type(cls.Type(d['dtype']))
|
|
852
|
+
shape = None if d['shape'] is None else tuple(d['shape'])
|
|
853
|
+
dtype = None if d['dtype'] is None else cls.make_type(cls.Type(d['dtype']))
|
|
837
854
|
return cls(shape, dtype, nullable=d['nullable'])
|
|
838
855
|
|
|
839
856
|
@classmethod
|
|
@@ -855,18 +872,30 @@ class ArrayType(ColumnType):
|
|
|
855
872
|
def is_valid_literal(self, val: np.ndarray) -> bool:
|
|
856
873
|
if not isinstance(val, np.ndarray):
|
|
857
874
|
return False
|
|
858
|
-
|
|
875
|
+
|
|
876
|
+
# If a dtype is specified, check that there's a match
|
|
877
|
+
if self.dtype is not None and not np.issubdtype(val.dtype, self.numpy_dtype()):
|
|
859
878
|
return False
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
879
|
+
|
|
880
|
+
# If no dtype is specified, we still need to check that the dtype is one of the supported types
|
|
881
|
+
if self.dtype is None and not any(
|
|
882
|
+
np.issubdtype(val.dtype, ndtype) for ndtype in [np.int64, np.float32, np.bool_, np.str_]
|
|
883
|
+
):
|
|
884
|
+
return False
|
|
885
|
+
|
|
886
|
+
# If a shape is specified, check that there's a match
|
|
887
|
+
if self.shape is not None:
|
|
888
|
+
if len(val.shape) != len(self.shape):
|
|
868
889
|
return False
|
|
869
|
-
|
|
890
|
+
# check that the shapes are compatible
|
|
891
|
+
for n1, n2 in zip(val.shape, self.shape):
|
|
892
|
+
assert n1 is not None # `val` must have a concrete shape
|
|
893
|
+
if n2 is None:
|
|
894
|
+
continue # wildcard
|
|
895
|
+
if n1 != n2:
|
|
896
|
+
return False
|
|
897
|
+
|
|
898
|
+
return True
|
|
870
899
|
|
|
871
900
|
def _to_json_schema(self) -> dict[str, Any]:
|
|
872
901
|
return {
|
|
@@ -878,9 +907,17 @@ class ArrayType(ColumnType):
|
|
|
878
907
|
if not isinstance(val, np.ndarray):
|
|
879
908
|
raise TypeError(f'Expected numpy.ndarray, got {val.__class__.__name__}')
|
|
880
909
|
if not self.is_valid_literal(val):
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
910
|
+
if self.shape is not None:
|
|
911
|
+
raise TypeError(
|
|
912
|
+
f'Expected numpy.ndarray({self.shape}, dtype={self.numpy_dtype()}), '
|
|
913
|
+
f'got numpy.ndarray({val.shape}, dtype={val.dtype})'
|
|
914
|
+
)
|
|
915
|
+
elif self.dtype is not None:
|
|
916
|
+
raise TypeError(
|
|
917
|
+
f'Expected numpy.ndarray of dtype {self.numpy_dtype()}, got numpy.ndarray of dtype {val.dtype}'
|
|
918
|
+
)
|
|
919
|
+
else:
|
|
920
|
+
raise TypeError(f'Unsupported dtype for numpy.ndarray: {val.dtype}')
|
|
884
921
|
|
|
885
922
|
def _create_literal(self, val: Any) -> Any:
|
|
886
923
|
if isinstance(val, (list, tuple)):
|
|
@@ -892,7 +929,9 @@ class ArrayType(ColumnType):
|
|
|
892
929
|
def to_sa_type(self) -> sql.types.TypeEngine:
|
|
893
930
|
return sql.LargeBinary()
|
|
894
931
|
|
|
895
|
-
def numpy_dtype(self) -> np.dtype:
|
|
932
|
+
def numpy_dtype(self) -> Optional[np.dtype]:
|
|
933
|
+
if self.dtype is None:
|
|
934
|
+
return None
|
|
896
935
|
if self.dtype == self.Type.INT:
|
|
897
936
|
return np.dtype(np.int64)
|
|
898
937
|
if self.dtype == self.Type.FLOAT:
|
|
@@ -901,7 +940,7 @@ class ArrayType(ColumnType):
|
|
|
901
940
|
return np.dtype(np.bool_)
|
|
902
941
|
if self.dtype == self.Type.STRING:
|
|
903
942
|
return np.dtype(np.str_)
|
|
904
|
-
assert False
|
|
943
|
+
assert False, self.dtype
|
|
905
944
|
|
|
906
945
|
|
|
907
946
|
class ImageType(ColumnType):
|
|
@@ -1174,6 +1213,8 @@ class Array(np.ndarray, _PxtType):
|
|
|
1174
1213
|
params = item if isinstance(item, tuple) else (item,)
|
|
1175
1214
|
shape: Optional[tuple] = None
|
|
1176
1215
|
dtype: Optional[ColumnType] = None
|
|
1216
|
+
if not any(isinstance(param, (type, _AnnotatedAlias)) for param in params):
|
|
1217
|
+
raise TypeError('Array type parameter must include a dtype.')
|
|
1177
1218
|
for param in params:
|
|
1178
1219
|
if isinstance(param, tuple):
|
|
1179
1220
|
if not all(n is None or (isinstance(n, int) and n >= 1) for n in param):
|
|
@@ -1181,21 +1222,17 @@ class Array(np.ndarray, _PxtType):
|
|
|
1181
1222
|
if shape is not None:
|
|
1182
1223
|
raise TypeError(f'Duplicate Array type parameter: {param}')
|
|
1183
1224
|
shape = param
|
|
1184
|
-
elif isinstance(param, type
|
|
1225
|
+
elif isinstance(param, (type, _AnnotatedAlias)):
|
|
1185
1226
|
if dtype is not None:
|
|
1186
1227
|
raise TypeError(f'Duplicate Array type parameter: {param}')
|
|
1187
1228
|
dtype = ColumnType.normalize_type(param, allow_builtin_types=False)
|
|
1188
1229
|
else:
|
|
1189
1230
|
raise TypeError(f'Invalid Array type parameter: {param}')
|
|
1190
|
-
if shape is None:
|
|
1191
|
-
raise TypeError('Array type is missing parameter: shape')
|
|
1192
|
-
if dtype is None:
|
|
1193
|
-
raise TypeError('Array type is missing parameter: dtype')
|
|
1194
1231
|
return typing.Annotated[np.ndarray, ArrayType(shape=shape, dtype=dtype, nullable=False)]
|
|
1195
1232
|
|
|
1196
1233
|
@classmethod
|
|
1197
1234
|
def as_col_type(cls, nullable: bool) -> ColumnType:
|
|
1198
|
-
|
|
1235
|
+
return ArrayType(nullable=nullable)
|
|
1199
1236
|
|
|
1200
1237
|
|
|
1201
1238
|
class Image(PIL.Image.Image, _PxtType):
|
pixeltable/utils/arrow.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
from typing import Any, Iterator, Optional, Union
|
|
3
2
|
|
|
4
3
|
import numpy as np
|
|
@@ -6,11 +5,7 @@ import pyarrow as pa
|
|
|
6
5
|
import datetime
|
|
7
6
|
|
|
8
7
|
import pixeltable.type_system as ts
|
|
9
|
-
from pixeltable.env import Env
|
|
10
8
|
|
|
11
|
-
_tz_def = Env().get().default_time_zone
|
|
12
|
-
|
|
13
|
-
_logger = logging.getLogger(__name__)
|
|
14
9
|
|
|
15
10
|
_pa_to_pt: dict[pa.DataType, ts.ColumnType] = {
|
|
16
11
|
pa.string(): ts.StringType(nullable=True),
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
def map_level(verbosity: int) -> int:
|
|
4
|
+
"""
|
|
5
|
+
Map verbosity level to logging level.
|
|
6
|
+
0 - minimum logging - warn and above
|
|
7
|
+
1 - default logging - info and above
|
|
8
|
+
2 - more logging - debug and above
|
|
9
|
+
Args:
|
|
10
|
+
|
|
11
|
+
Returns:
|
|
12
|
+
Logging level as integer
|
|
13
|
+
"""
|
|
14
|
+
if verbosity == 0:
|
|
15
|
+
return logging.WARN
|
|
16
|
+
if verbosity == 1:
|
|
17
|
+
return logging.INFO
|
|
18
|
+
if verbosity == 2:
|
|
19
|
+
return logging.DEBUG
|
|
20
|
+
return logging.INFO
|
|
21
|
+
|
|
22
|
+
class ConsoleOutputHandler(logging.StreamHandler):
|
|
23
|
+
def __init__(self, stream):
|
|
24
|
+
super().__init__(stream)
|
|
25
|
+
|
|
26
|
+
def emit(self, record):
|
|
27
|
+
if record.msg.endswith('\n'):
|
|
28
|
+
self.stream.write(record.msg)
|
|
29
|
+
else:
|
|
30
|
+
self.stream.write(record.msg + '\n')
|
|
31
|
+
|
|
32
|
+
class ConsoleMessageFilter(logging.Filter):
|
|
33
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
|
34
|
+
if hasattr(record, 'user_visible') and record.user_visible:
|
|
35
|
+
return True
|
|
36
|
+
return False
|
|
37
|
+
|
|
38
|
+
class ConsoleLogger(logging.LoggerAdapter):
|
|
39
|
+
def __init__(self, logger:logging.Logger):
|
|
40
|
+
super().__init__(logger, extra={'user_visible' : True})
|
|
41
|
+
|
pixeltable/utils/filecache.py
CHANGED
|
@@ -239,4 +239,4 @@ class FileCache:
|
|
|
239
239
|
|
|
240
240
|
def debug_print(self) -> None:
|
|
241
241
|
for entry in self.cache.values():
|
|
242
|
-
|
|
242
|
+
_logger.debug(f'CacheEntry: tbl_id={entry.tbl_id}, col_id={entry.col_id}, size={entry.size}')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pixeltable
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: AI Data Infrastructure: Declarative, Multimodal, and Incremental
|
|
5
5
|
Home-page: https://pixeltable.com/
|
|
6
6
|
License: Apache-2.0
|
|
@@ -27,6 +27,7 @@ Requires-Dist: av (>=10.0.0)
|
|
|
27
27
|
Requires-Dist: beautifulsoup4 (>=4.0.0,<5.0.0)
|
|
28
28
|
Requires-Dist: cloudpickle (>=2.2.1,<3.0.0)
|
|
29
29
|
Requires-Dist: ftfy (>=6.2.0,<7.0.0)
|
|
30
|
+
Requires-Dist: httpcore (>=1.0.3)
|
|
30
31
|
Requires-Dist: httpx (>=0.27)
|
|
31
32
|
Requires-Dist: jinja2 (>=3.1.3,<4.0.0)
|
|
32
33
|
Requires-Dist: jmespath (>=1.0.1,<2.0.0)
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
pixeltable/__init__.py,sha256=c-Z21TqJUbzGQKsO4CS4lVFwWlZnVhpIR94cL6RNmDo,1411
|
|
2
|
-
pixeltable/__version__.py,sha256=
|
|
2
|
+
pixeltable/__version__.py,sha256=Ftdd_iaB0tNUSNnDBsJFrHIR6gBXSgcgIbcjGk_8ds4,112
|
|
3
3
|
pixeltable/catalog/__init__.py,sha256=u8Ods4ncTY7DI5w0jyHVC0QDVDLHAy8Rqia3qsM5OH8,517
|
|
4
4
|
pixeltable/catalog/catalog.py,sha256=tyDyI5wQw7vV6_FChrp9qgGCRClcjiSdW3eygYT0p9s,7849
|
|
5
5
|
pixeltable/catalog/column.py,sha256=ezeKoGl6aBTzSZBihDA6vdETcvyCguAD4OsmrxWs73A,9595
|
|
6
6
|
pixeltable/catalog/dir.py,sha256=-dV0-gn5GfqRmVIJbuUBOXqPuNLDm219cud_kBTNzuk,1203
|
|
7
7
|
pixeltable/catalog/globals.py,sha256=VgcmwtKYYDQtvtHShVde52n4FzGBtAIFYxoS-WD7OBw,3242
|
|
8
|
-
pixeltable/catalog/insertable_table.py,sha256=
|
|
8
|
+
pixeltable/catalog/insertable_table.py,sha256=VgZ6C0l_NI1orCqeZF_lOC5RZnie36_bQSx3y6SRtW4,7227
|
|
9
9
|
pixeltable/catalog/named_function.py,sha256=cWf9WxAagSY9uqE7mM0IwWSsDOvQUkJlcHlGqgVciJg,1225
|
|
10
10
|
pixeltable/catalog/path.py,sha256=QgccEi_QOfaKt8YsR2zLtd_z7z7QQkU_1kprJFi2SPQ,1677
|
|
11
11
|
pixeltable/catalog/path_dict.py,sha256=V7YQM0QhUWr4FbgUiDUIweGbmMJr687QCm2p614Xrs0,6473
|
|
12
12
|
pixeltable/catalog/schema_object.py,sha256=NUE6Fx6Km0UUJ6WcE9mOgL2UQCLBMQjINQLp_mljzKA,2382
|
|
13
|
-
pixeltable/catalog/table.py,sha256=
|
|
14
|
-
pixeltable/catalog/table_version.py,sha256=
|
|
13
|
+
pixeltable/catalog/table.py,sha256=DbCX6H1xZL3raytoMrii0ceZiwD_X4FhkUw-1Djuaf0,62460
|
|
14
|
+
pixeltable/catalog/table_version.py,sha256=Ue_iByiT9JdPl_QwXnwq93Nd71Z_w0BHlRjugOLSI60,58625
|
|
15
15
|
pixeltable/catalog/table_version_path.py,sha256=CczGbcz5ESq663arreri_p4chMZHozgG6k3y-ajkJN4,5787
|
|
16
|
-
pixeltable/catalog/view.py,sha256=
|
|
16
|
+
pixeltable/catalog/view.py,sha256=hzTzS2jtrE8fyI5IeCKlmUQl_w-xE0C0fslmdBOBBZU,10733
|
|
17
17
|
pixeltable/dataframe.py,sha256=KrAB-l_qdArlT3pnlSH69k0mqs0AK2wFhQ4V_7Wcjyw,48639
|
|
18
|
-
pixeltable/env.py,sha256=
|
|
18
|
+
pixeltable/env.py,sha256=J0e2dN42O6u1N67sg4OIyBKcElbSueQWdRFBC_8LFRY,35776
|
|
19
19
|
pixeltable/exceptions.py,sha256=NuFY2WtkQpLfLHT_J70kOw9Tr0kEDkkgo-u7As4Gaq4,410
|
|
20
20
|
pixeltable/exec/__init__.py,sha256=E_ub_ftAJVebEmKHZs47egeJqMfAbbx4SS1l7jR-Nd0,489
|
|
21
21
|
pixeltable/exec/aggregation_node.py,sha256=iE3UHHW0IbkHsY7kYJAg6m1UKyKUu2_tJuzgL_rQUVE,4038
|
|
@@ -25,11 +25,11 @@ pixeltable/exec/data_row_batch.py,sha256=5WhdS3ahtCP3wROw4NPJjtvaQUAWKwyN1rHKbfd
|
|
|
25
25
|
pixeltable/exec/exec_context.py,sha256=-FbfYLcGOL7mviru5dE1A7x4YxLbdKoXBHN3OSbqbcg,1084
|
|
26
26
|
pixeltable/exec/exec_node.py,sha256=qDp63PFlMQUVwav0JIjuP0r0BH9EwW7s_NgqFE_Zn20,3735
|
|
27
27
|
pixeltable/exec/expr_eval/__init__.py,sha256=t0o2T7MxfH09TI7KlzxEjPUySejn2vkK06LC8t4FjsQ,41
|
|
28
|
-
pixeltable/exec/expr_eval/evaluators.py,sha256=
|
|
29
|
-
pixeltable/exec/expr_eval/expr_eval_node.py,sha256=
|
|
30
|
-
pixeltable/exec/expr_eval/globals.py,sha256=
|
|
28
|
+
pixeltable/exec/expr_eval/evaluators.py,sha256=Zb_TW_VLiicVSVZjbmU4eSDzuzO37J6VIvmLZo5fjPY,11061
|
|
29
|
+
pixeltable/exec/expr_eval/expr_eval_node.py,sha256=XSddV59hHkhUGKeRYgbviY5GcB0p61Y9qzIvBcdwpXM,19911
|
|
30
|
+
pixeltable/exec/expr_eval/globals.py,sha256=q3WBI5HRBxgg2msrqcZhuh1oZ_KkI4i1MzICjePGIwM,3856
|
|
31
31
|
pixeltable/exec/expr_eval/row_buffer.py,sha256=Wjc6ZklxSW4-sCAMEGIzESII1uuC6Urzmq6JeUO3ALA,2737
|
|
32
|
-
pixeltable/exec/expr_eval/schedulers.py,sha256=
|
|
32
|
+
pixeltable/exec/expr_eval/schedulers.py,sha256=_Tq_JglwcAI_rvhDgWm0tVH2eBPCOsHctoZaK-jiFlo,11257
|
|
33
33
|
pixeltable/exec/in_memory_data_node.py,sha256=CwuwkA2xdyApMfPfSQamlLdbb-IQn7R7zeBBJiI8I7g,3479
|
|
34
34
|
pixeltable/exec/row_update_node.py,sha256=MEvI3Yzw6YcUDTufSNVNVtyG83Hj6zHzEI9fvKtAgRQ,2859
|
|
35
35
|
pixeltable/exec/sql_node.py,sha256=vMHNHzhrlk2Ej58vMZzk7hYAeHFHlBtkLwYZsOVn3CQ,19573
|
|
@@ -54,7 +54,7 @@ pixeltable/exprs/json_path.py,sha256=UTf3VUcyEmEBJs6yU4kONGcZ8fy1o6mIe9MlntnUd6M
|
|
|
54
54
|
pixeltable/exprs/literal.py,sha256=Nhh-fXYMqGL4Tfm2YiFUd4ALMjzG7nJ2H4jHZe9XS1Y,4394
|
|
55
55
|
pixeltable/exprs/method_ref.py,sha256=3O_uFMP6wWGiwJWri8on-47EVl-QD3AiAc7hXJMADxs,2615
|
|
56
56
|
pixeltable/exprs/object_ref.py,sha256=GVg6uxZnKwFVTC0kouJq-wMFP-gUPb_ld_syHrsGMdE,1283
|
|
57
|
-
pixeltable/exprs/row_builder.py,sha256=
|
|
57
|
+
pixeltable/exprs/row_builder.py,sha256=hR-lpd9BDsPesJQ_02Mh0NB3Kou8ELIUnchGI1e--vg,19916
|
|
58
58
|
pixeltable/exprs/rowid_ref.py,sha256=iNBZ0wIhBAGkGCrNP9UQ2FeK8OajVX-eI4dtDA_bfHU,4401
|
|
59
59
|
pixeltable/exprs/similarity_expr.py,sha256=GhiopGxN3wu5MOEqfWN4PNbqgSszg2VIC1_bqVPpm3Q,4333
|
|
60
60
|
pixeltable/exprs/sql_element_cache.py,sha256=8i9ZslKWKTd1lUN7JvwRtQ-PFD1QMi5LBYdwcGA2-p0,1364
|
|
@@ -76,7 +76,7 @@ pixeltable/func/signature.py,sha256=wWf07OawOwDmqZOjUPgHJHAhAQ-fd61PGBx82aWLBgA,
|
|
|
76
76
|
pixeltable/func/tools.py,sha256=7OAHVb9KbmcPtfMWsbKAoRu3kx-_japSTE-hgRQJefM,5988
|
|
77
77
|
pixeltable/func/udf.py,sha256=p7imgwk7S03q3lHZxqAZUKr63XSeSsrD8kWTbwOLQWo,8882
|
|
78
78
|
pixeltable/functions/__init__.py,sha256=C7Okwst3JdhzwIFWXhyJ3F0EHKGKor2R8dRMvQ3y6Us,428
|
|
79
|
-
pixeltable/functions/anthropic.py,sha256=
|
|
79
|
+
pixeltable/functions/anthropic.py,sha256=tAMImdf-L6ZBnHGbX98uM5VuPkiwxzDAjdMZsY26lPI,8866
|
|
80
80
|
pixeltable/functions/audio.py,sha256=7213nTnqKJ6vM9kalaoJ283OwX5SGEJN10vDhaRNZ6E,644
|
|
81
81
|
pixeltable/functions/fireworks.py,sha256=qwFC_eIaDs-glxyJ_IVXaNGkpgPzeRsQ_SdpzueBxq0,2605
|
|
82
82
|
pixeltable/functions/gemini.py,sha256=0aqsDpxI0AgeWu6zXQxtFbp3nhhuwXqzulZyot6UKdg,2613
|
|
@@ -88,7 +88,7 @@ pixeltable/functions/llama_cpp.py,sha256=1awALuAXVpQH64l7vQlM8gvxLDix4c1-6DV3nG5
|
|
|
88
88
|
pixeltable/functions/math.py,sha256=WPoH9zD9_GdwvBs-FSC3Sqb70gOPNouhPcBZABsuLwI,1541
|
|
89
89
|
pixeltable/functions/mistralai.py,sha256=GpxtT-a8ltx1kQC8XTJRflxkh-17VhzzFTkxqIUsba8,5494
|
|
90
90
|
pixeltable/functions/ollama.py,sha256=z-g0cCJ-WMf6RI3SXIVVbbOlrWNR8nxGTyzET1rratU,4320
|
|
91
|
-
pixeltable/functions/openai.py,sha256=
|
|
91
|
+
pixeltable/functions/openai.py,sha256=kXIhIMB2wNrrUO81H7ycy30avhgRApKepnkhE3C4uxA,24606
|
|
92
92
|
pixeltable/functions/replicate.py,sha256=j8ZedScOMInmHWmriQSUOviw6tp8gQr-W6n21PNNL2g,2188
|
|
93
93
|
pixeltable/functions/string.py,sha256=VqzhVildxTt_XblW89Kl5Zd6MVOU71eaX2LTMY5jkUg,20366
|
|
94
94
|
pixeltable/functions/timestamp.py,sha256=KOm5eVF51PqOCTqwq8cKCAEJNWMgu2xN_yTtGf7yixU,9095
|
|
@@ -97,7 +97,7 @@ pixeltable/functions/util.py,sha256=GgKTzCjvzUQNjWtSObTkfxkvJ9GVUOzKimY45WhE25M,
|
|
|
97
97
|
pixeltable/functions/video.py,sha256=12jnOdU0G-Hk42rJx-S5QC77-bDkUflkxfkjej8n5pM,6702
|
|
98
98
|
pixeltable/functions/vision.py,sha256=MEgkNp-4tUUeQS05VEJBrMgQFM48aNsNlksfAl9rH7w,15494
|
|
99
99
|
pixeltable/functions/whisper.py,sha256=f2wqRd0n9jSBqRZN3W93UaetiAHtbsK0j9jXR2j2kkQ,2913
|
|
100
|
-
pixeltable/globals.py,sha256=
|
|
100
|
+
pixeltable/globals.py,sha256=7gYQdZs685OwJm1W49g4LlRdrhzhKTSU_DpJr_MRaXg,33866
|
|
101
101
|
pixeltable/index/__init__.py,sha256=XBwetNQQwnz0fiKwonOKhyy_U32l_cjt77kNvEIdjWs,102
|
|
102
102
|
pixeltable/index/base.py,sha256=zo0YvJI3oXiK6hZJztB36ZftKKhLfO75Zq3t-PeQA6M,1556
|
|
103
103
|
pixeltable/index/btree.py,sha256=JFerLyyLoBaD0FSF_jJ6iJFBVa-z_et--KdNR02xjRg,2264
|
|
@@ -106,17 +106,17 @@ pixeltable/io/__init__.py,sha256=j3qDyGO1ejLce-UzIncK3eRqyOCLoOlDqClecMBSJGc,563
|
|
|
106
106
|
pixeltable/io/external_store.py,sha256=H1jt7MDn464QRgBvU-PmcPcFlo3EZBCG7fKWEZXOfyc,16676
|
|
107
107
|
pixeltable/io/fiftyone.py,sha256=hH-FahW6BuMQY8lGa2atnNnJto_pK8kWrP_y_EMsq6g,6965
|
|
108
108
|
pixeltable/io/globals.py,sha256=9S9wnlIAuhZq7eC_GklTM_UX0UATK9fEagk8-SRCeXQ,17794
|
|
109
|
-
pixeltable/io/hf_datasets.py,sha256=
|
|
110
|
-
pixeltable/io/label_studio.py,sha256=
|
|
109
|
+
pixeltable/io/hf_datasets.py,sha256=1_NRn1748OT69UlBpnb_AWkEitEHrYiRO4vbJ7XwdQw,8320
|
|
110
|
+
pixeltable/io/label_studio.py,sha256=RtupR5mtql0NUHnoocCdfOhYfO6ienS9_lhEztx6ECU,31231
|
|
111
111
|
pixeltable/io/pandas.py,sha256=7eHg7wnAfRA9eBk4iC0iSSVTKOM59Ne4pXokKWdt3dY,9793
|
|
112
|
-
pixeltable/io/parquet.py,sha256=
|
|
112
|
+
pixeltable/io/parquet.py,sha256=3n-4XgCVS8-V3fph_meyDOrvz-f_a-7WbvKMTEfYNUY,8804
|
|
113
113
|
pixeltable/iterators/__init__.py,sha256=qA9cJTwPO3gk-7y8mUXw2anWSbnUAVGwzl52SxiUjNU,398
|
|
114
114
|
pixeltable/iterators/base.py,sha256=ZC0ZvXL4iw6AmT8cu-Mdx-T2UG9nmJYV1C6LK4efAfw,1669
|
|
115
115
|
pixeltable/iterators/document.py,sha256=e5EMUAW4f5SqfC5mRN7Oo2E3gw_vcMSzq2707NVLByU,20254
|
|
116
116
|
pixeltable/iterators/image.py,sha256=7eJupbyLEl_q4bemEozL8WgTgkxjl-DYnSXyHTQ7Rck,3628
|
|
117
117
|
pixeltable/iterators/string.py,sha256=NG_fWc_GAITDfzl6MvrDOMrSoMcZdMZf6hPQztCSatE,1305
|
|
118
118
|
pixeltable/iterators/video.py,sha256=anedQpSOnjYhHLa8UiEx-6ROagb14rpXh9am8oTriUg,9382
|
|
119
|
-
pixeltable/metadata/__init__.py,sha256=
|
|
119
|
+
pixeltable/metadata/__init__.py,sha256=7Ep8e48O7sLiNxarTF_kDunRn7maaj7tTBYUPC76VnI,2276
|
|
120
120
|
pixeltable/metadata/converters/convert_10.py,sha256=J1_r7LNNAWTdb042AwqFpJ4sEB-i4qhUdk5iOjcZk34,719
|
|
121
121
|
pixeltable/metadata/converters/convert_12.py,sha256=Ci-qyZW1gqci-8wnjeOB5afdq7KTuN-hVSV9OqSPx8g,162
|
|
122
122
|
pixeltable/metadata/converters/convert_13.py,sha256=yFR6lD3pOrZ46ZQBFKYvxiIYa7rRxh46Bsq7yiCBNak,1356
|
|
@@ -138,14 +138,15 @@ pixeltable/metadata/schema.py,sha256=H9t51cbhXOhNu9Xog2VTjZlkTCx4cjQAlwOXi3HSd2E
|
|
|
138
138
|
pixeltable/plan.py,sha256=DgzP5kDmBooaUioZ0KBlSUcx_jpqy456CnbDRVzFBJM,41501
|
|
139
139
|
pixeltable/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
140
140
|
pixeltable/store.py,sha256=-A7oRGHDpvhUZzx68QSde0t2NvUjeM1rOw9KdwukQ9s,22497
|
|
141
|
-
pixeltable/type_system.py,sha256=
|
|
141
|
+
pixeltable/type_system.py,sha256=t7IOdQj90vBriJiexuSkmx-RSbzZYoijmX9FqYC778s,50019
|
|
142
142
|
pixeltable/utils/__init__.py,sha256=UYlrf6TIWJT0g-Hac0b34-dEk478B5Qx8dGco34YlIk,439
|
|
143
|
-
pixeltable/utils/arrow.py,sha256=
|
|
143
|
+
pixeltable/utils/arrow.py,sha256=Fb6dLTC7jiTMH6l2UoVlrcnoIbe-mJH2zmpBFIjajKo,3866
|
|
144
144
|
pixeltable/utils/coco.py,sha256=WCUyoj0dTyJFbPB7frEQUvY92SlEPxQ068r-3QAwROE,7285
|
|
145
145
|
pixeltable/utils/code.py,sha256=AOw1u2r8_DQXpX-lxJhyHWARGrCRDXOJHFVgKOi54Uc,1231
|
|
146
|
+
pixeltable/utils/console_output.py,sha256=SB4ibt43-HqIUkv3SR93xyEcu8WhjwPSpMlAs6xyejc,1145
|
|
146
147
|
pixeltable/utils/description_helper.py,sha256=P-8EE2pRFP8s3coe73frgV68yt4Dp3saErCUehMxKUw,3759
|
|
147
148
|
pixeltable/utils/documents.py,sha256=pytTYY167wYc1rGaDd9HPK6GOrz1ML78eAD3hIHrG68,2930
|
|
148
|
-
pixeltable/utils/filecache.py,sha256=
|
|
149
|
+
pixeltable/utils/filecache.py,sha256=kgRf5tlNZN642wrYIf5qpUMSA8ULHmnoIrvhkR0MwYU,10645
|
|
149
150
|
pixeltable/utils/formatter.py,sha256=5E_gDg11ClFI-5SthwkiqyE3hAok3JHDj4OSK9cJklM,9257
|
|
150
151
|
pixeltable/utils/http_server.py,sha256=xYPTvmYrkUpKfOaLDq08D-eHswkcgDf4qAt76ZFH6lM,2411
|
|
151
152
|
pixeltable/utils/media_store.py,sha256=YwvTjbVqC_aLbDvLuqnDSL8xeIVMZcmzp0ANuM6uMbw,3092
|
|
@@ -153,8 +154,8 @@ pixeltable/utils/pytorch.py,sha256=6RvOCjy_QV4gc-aht-3d0zoASkuv-warfpl87vgmuKw,3
|
|
|
153
154
|
pixeltable/utils/s3.py,sha256=huA5hxDGkPIu18zWet76o0FsO7Vbtp-iPmnOzCe-MvA,586
|
|
154
155
|
pixeltable/utils/sql.py,sha256=j_tj0h4ffm-DhUIJbvGphxrVyBKlNTwDKqWGhRQ5_PY,795
|
|
155
156
|
pixeltable/utils/transactional_directory.py,sha256=UGzCrGtLR3hEEf8sYGuWBzLVFAEQml3vdIavigWeTBM,1349
|
|
156
|
-
pixeltable-0.3.
|
|
157
|
-
pixeltable-0.3.
|
|
158
|
-
pixeltable-0.3.
|
|
159
|
-
pixeltable-0.3.
|
|
160
|
-
pixeltable-0.3.
|
|
157
|
+
pixeltable-0.3.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
158
|
+
pixeltable-0.3.2.dist-info/METADATA,sha256=-8DaK2FpbjMasYQkI49akVlIuoPnhMWA0lKLQ_5Ww-o,19404
|
|
159
|
+
pixeltable-0.3.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
160
|
+
pixeltable-0.3.2.dist-info/entry_points.txt,sha256=ToOd-pRgG7AitEBgYoBCRRB4-KVDQ0pj_9T4a1LgwA4,97
|
|
161
|
+
pixeltable-0.3.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|