pixeltable 0.2.11__py3-none-any.whl → 0.2.12__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pixeltable might be problematic. Click here for more details.
- pixeltable/__init__.py +2 -2
- pixeltable/__version__.py +2 -2
- pixeltable/catalog/schema_object.py +28 -2
- pixeltable/catalog/table.py +63 -25
- pixeltable/catalog/table_version.py +2 -29
- pixeltable/dataframe.py +1 -1
- pixeltable/exprs/column_ref.py +2 -7
- pixeltable/exprs/similarity_expr.py +27 -16
- pixeltable/functions/openai.py +1 -1
- pixeltable/globals.py +51 -47
- pixeltable/index/embedding_index.py +28 -27
- pixeltable/io/external_store.py +2 -2
- pixeltable/io/globals.py +1 -1
- pixeltable/io/label_studio.py +3 -3
- pixeltable/metadata/__init__.py +1 -1
- pixeltable/metadata/converters/convert_17.py +26 -0
- pixeltable/tool/create_test_db_dump.py +1 -1
- {pixeltable-0.2.11.dist-info → pixeltable-0.2.12.dist-info}/METADATA +3 -3
- {pixeltable-0.2.11.dist-info → pixeltable-0.2.12.dist-info}/RECORD +21 -20
- {pixeltable-0.2.11.dist-info → pixeltable-0.2.12.dist-info}/LICENSE +0 -0
- {pixeltable-0.2.11.dist-info → pixeltable-0.2.12.dist-info}/WHEEL +0 -0
pixeltable/__init__.py
CHANGED
|
@@ -3,8 +3,8 @@ from .dataframe import DataFrame
|
|
|
3
3
|
from .exceptions import Error
|
|
4
4
|
from .exprs import RELATIVE_PATH_ROOT
|
|
5
5
|
from .func import Function, udf, Aggregator, uda, expr_udf
|
|
6
|
-
from .globals import init, create_table, create_view, get_table, move, drop_table, list_tables, create_dir,
|
|
7
|
-
list_dirs, list_functions,
|
|
6
|
+
from .globals import init, create_table, create_view, get_table, move, drop_table, list_tables, create_dir, drop_dir, \
|
|
7
|
+
list_dirs, list_functions, configure_logging
|
|
8
8
|
from .type_system import (
|
|
9
9
|
ColumnType,
|
|
10
10
|
StringType,
|
pixeltable/__version__.py
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
# These version placeholders will be replaced during build.
|
|
2
|
-
__version__ = "0.2.
|
|
3
|
-
__version_tuple__ = (0, 2,
|
|
2
|
+
__version__ = "0.2.12"
|
|
3
|
+
__version_tuple__ = (0, 2, 12)
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
|
-
from typing import Optional
|
|
2
|
+
from typing import TYPE_CHECKING, Optional
|
|
3
3
|
from uuid import UUID
|
|
4
4
|
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from pixeltable import catalog
|
|
7
|
+
|
|
5
8
|
|
|
6
9
|
class SchemaObject:
|
|
7
10
|
"""
|
|
@@ -17,9 +20,32 @@ class SchemaObject:
|
|
|
17
20
|
def _get_id(self) -> UUID:
|
|
18
21
|
return self._id
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
@property
|
|
24
|
+
def name(self) -> str:
|
|
25
|
+
"""Returns the name of this schema object."""
|
|
21
26
|
return self._name
|
|
22
27
|
|
|
28
|
+
@property
|
|
29
|
+
def parent(self) -> Optional['catalog.Dir']:
|
|
30
|
+
"""Returns the parent directory of this schema object."""
|
|
31
|
+
from pixeltable import catalog
|
|
32
|
+
if self._dir_id is None:
|
|
33
|
+
return None
|
|
34
|
+
dir = catalog.Catalog.get().paths.get_schema_obj(self._dir_id)
|
|
35
|
+
assert isinstance(dir, catalog.Dir)
|
|
36
|
+
return dir
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def path(self) -> str:
|
|
40
|
+
"""Returns the path to this schema object."""
|
|
41
|
+
parent = self.parent
|
|
42
|
+
if parent is None or parent.parent is None:
|
|
43
|
+
# Either this is the root directory, with empty path, or its parent is the
|
|
44
|
+
# root directory. Either way, we return just the name.
|
|
45
|
+
return self.name
|
|
46
|
+
else:
|
|
47
|
+
return f'{parent.path}.{self.name}'
|
|
48
|
+
|
|
23
49
|
@classmethod
|
|
24
50
|
@abstractmethod
|
|
25
51
|
def display_name(cls) -> str:
|
pixeltable/catalog/table.py
CHANGED
|
@@ -82,14 +82,22 @@ class Table(SchemaObject):
|
|
|
82
82
|
return self._queries[index]
|
|
83
83
|
return self._tbl_version_path.__getitem__(index)
|
|
84
84
|
|
|
85
|
-
def
|
|
85
|
+
def list_views(self, *, recursive: bool = True) -> list[str]:
|
|
86
86
|
"""
|
|
87
|
-
|
|
87
|
+
Returns a list of all views and snapshots of this `Table`.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
recursive: If `False`, returns only the immediate successor views of this `Table`. If `True`, returns
|
|
91
|
+
all sub-views (including views of views, etc.)
|
|
88
92
|
"""
|
|
93
|
+
return [t.path for t in self._get_views(recursive=recursive)]
|
|
94
|
+
|
|
95
|
+
def _get_views(self, *, recursive: bool = True) -> list['Table']:
|
|
96
|
+
dependents = catalog.Catalog.get().tbl_dependents[self._get_id()]
|
|
89
97
|
if recursive:
|
|
90
|
-
return
|
|
98
|
+
return dependents + [t for view in dependents for t in view._get_views(recursive=True)]
|
|
91
99
|
else:
|
|
92
|
-
return
|
|
100
|
+
return dependents
|
|
93
101
|
|
|
94
102
|
def _df(self) -> 'pixeltable.dataframe.DataFrame':
|
|
95
103
|
"""Return a DataFrame for this table.
|
|
@@ -500,7 +508,37 @@ class Table(SchemaObject):
|
|
|
500
508
|
>>> tbl.drop_column('factorial')
|
|
501
509
|
"""
|
|
502
510
|
self._check_is_dropped()
|
|
503
|
-
|
|
511
|
+
|
|
512
|
+
if name not in self._tbl_version.cols_by_name:
|
|
513
|
+
raise excs.Error(f'Unknown column: {name}')
|
|
514
|
+
col = self._tbl_version.cols_by_name[name]
|
|
515
|
+
|
|
516
|
+
dependent_user_cols = [c for c in col.dependent_cols if c.name is not None]
|
|
517
|
+
if len(dependent_user_cols) > 0:
|
|
518
|
+
raise excs.Error(
|
|
519
|
+
f'Cannot drop column `{name}` because the following columns depend on it:\n'
|
|
520
|
+
f'{", ".join(c.name for c in dependent_user_cols)}'
|
|
521
|
+
)
|
|
522
|
+
|
|
523
|
+
# See if this column has a dependent store. We need to look through all stores in all
|
|
524
|
+
# (transitive) views of this table.
|
|
525
|
+
dependent_stores = [
|
|
526
|
+
(view, store)
|
|
527
|
+
for view in [self] + self._get_views(recursive=True)
|
|
528
|
+
for store in view._tbl_version.external_stores.values()
|
|
529
|
+
if col in store.get_local_columns()
|
|
530
|
+
]
|
|
531
|
+
if len(dependent_stores) > 0:
|
|
532
|
+
dependent_store_names = [
|
|
533
|
+
store.name if view._get_id() == self._get_id() else f'{store.name} (in view `{view.name}`)'
|
|
534
|
+
for view, store in dependent_stores
|
|
535
|
+
]
|
|
536
|
+
raise excs.Error(
|
|
537
|
+
f'Cannot drop column `{name}` because the following external stores depend on it:\n'
|
|
538
|
+
f'{", ".join(dependent_store_names)}'
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
self._tbl_version.drop_column(col)
|
|
504
542
|
|
|
505
543
|
def rename_column(self, old_name: str, new_name: str) -> None:
|
|
506
544
|
"""Rename a column.
|
|
@@ -522,15 +560,15 @@ class Table(SchemaObject):
|
|
|
522
560
|
|
|
523
561
|
def add_embedding_index(
|
|
524
562
|
self, col_name: str, *, idx_name: Optional[str] = None,
|
|
525
|
-
|
|
563
|
+
string_embed: Optional[pixeltable.Function] = None, image_embed: Optional[pixeltable.Function] = None,
|
|
526
564
|
metric: str = 'cosine'
|
|
527
565
|
) -> None:
|
|
528
566
|
"""Add an index to the table.
|
|
529
567
|
Args:
|
|
530
568
|
col_name: name of column to index
|
|
531
569
|
idx_name: name of index, which needs to be unique for the table; if not provided, a name will be generated
|
|
532
|
-
|
|
533
|
-
|
|
570
|
+
string_embed: function to embed text; required if the column is a text column
|
|
571
|
+
image_embed: function to embed images; required if the column is an image column
|
|
534
572
|
metric: distance metric to use for the index; one of 'cosine', 'ip', 'l2'; default is 'cosine'
|
|
535
573
|
|
|
536
574
|
Raises:
|
|
@@ -539,13 +577,13 @@ class Table(SchemaObject):
|
|
|
539
577
|
Examples:
|
|
540
578
|
Add an index to the ``img`` column:
|
|
541
579
|
|
|
542
|
-
>>> tbl.add_embedding_index('img',
|
|
580
|
+
>>> tbl.add_embedding_index('img', image_embed=...)
|
|
543
581
|
|
|
544
582
|
Add another index to the ``img`` column, using the inner product as the distance metric,
|
|
545
|
-
and with a specific name; ``
|
|
583
|
+
and with a specific name; ``string_embed`` is also specified in order to search with text:
|
|
546
584
|
|
|
547
585
|
>>> tbl.add_embedding_index(
|
|
548
|
-
'img', idx_name='clip_idx',
|
|
586
|
+
'img', idx_name='clip_idx', image_embed=..., string_embed=..., metric='ip')
|
|
549
587
|
"""
|
|
550
588
|
if self._tbl_version_path.is_snapshot():
|
|
551
589
|
raise excs.Error('Cannot add an index to a snapshot')
|
|
@@ -557,7 +595,7 @@ class Table(SchemaObject):
|
|
|
557
595
|
raise excs.Error(f'Duplicate index name: {idx_name}')
|
|
558
596
|
from pixeltable.index import EmbeddingIndex
|
|
559
597
|
# create the EmbeddingIndex instance to verify args
|
|
560
|
-
idx = EmbeddingIndex(col, metric=metric,
|
|
598
|
+
idx = EmbeddingIndex(col, metric=metric, string_embed=string_embed, image_embed=image_embed)
|
|
561
599
|
status = self._tbl_version.add_index(col, idx_name=idx_name, idx=idx)
|
|
562
600
|
# TODO: how to deal with exceptions here? drop the index and raise?
|
|
563
601
|
|
|
@@ -604,26 +642,26 @@ class Table(SchemaObject):
|
|
|
604
642
|
raise excs.Error('Cannot drop an index from a snapshot')
|
|
605
643
|
self._check_is_dropped()
|
|
606
644
|
if (column_name is None) == (idx_name is None):
|
|
607
|
-
raise excs.Error(
|
|
645
|
+
raise excs.Error("Exactly one of 'column_name' or 'idx_name' must be provided")
|
|
608
646
|
|
|
609
647
|
if idx_name is not None:
|
|
610
648
|
if idx_name not in self._tbl_version.idxs_by_name:
|
|
611
|
-
raise excs.Error(f'Index {idx_name} does not exist')
|
|
649
|
+
raise excs.Error(f'Index {idx_name!r} does not exist')
|
|
612
650
|
idx_id = self._tbl_version.idxs_by_name[idx_name].id
|
|
613
651
|
else:
|
|
614
652
|
col = self._tbl_version_path.get_column(column_name, include_bases=True)
|
|
615
653
|
if col is None:
|
|
616
|
-
raise excs.Error(f'Column {column_name} unknown')
|
|
654
|
+
raise excs.Error(f'Column {column_name!r} unknown')
|
|
617
655
|
if col.tbl.id != self._tbl_version.id:
|
|
618
656
|
raise excs.Error(
|
|
619
|
-
f'Column {column_name}: cannot drop index from column that belongs to base ({col.tbl.name})')
|
|
657
|
+
f'Column {column_name!r}: cannot drop index from column that belongs to base ({col.tbl.name}!r)')
|
|
620
658
|
idx_info = [info for info in self._tbl_version.idxs_by_name.values() if info.col.id == col.id]
|
|
621
659
|
if _idx_class is not None:
|
|
622
660
|
idx_info = [info for info in idx_info if isinstance(info.idx, _idx_class)]
|
|
623
661
|
if len(idx_info) == 0:
|
|
624
|
-
raise excs.Error(f'Column {column_name} does not have an index')
|
|
662
|
+
raise excs.Error(f'Column {column_name!r} does not have an index')
|
|
625
663
|
if len(idx_info) > 1:
|
|
626
|
-
raise excs.Error(f
|
|
664
|
+
raise excs.Error(f"Column {column_name!r} has multiple indices; specify 'idx_name' instead")
|
|
627
665
|
idx_id = idx_info[0].id
|
|
628
666
|
self._tbl_version.drop_index(idx_id)
|
|
629
667
|
|
|
@@ -823,13 +861,13 @@ class Table(SchemaObject):
|
|
|
823
861
|
Links the specified `ExternalStore` to this table.
|
|
824
862
|
"""
|
|
825
863
|
if self._tbl_version.is_snapshot:
|
|
826
|
-
raise excs.Error(f'Table `{self.
|
|
864
|
+
raise excs.Error(f'Table `{self.name}` is a snapshot, so it cannot be linked to an external store.')
|
|
827
865
|
self._check_is_dropped()
|
|
828
866
|
if store.name in self.external_stores:
|
|
829
|
-
raise excs.Error(f'Table `{self.
|
|
830
|
-
_logger.info(f'Linking external store `{store.name}` to table `{self.
|
|
867
|
+
raise excs.Error(f'Table `{self.name}` already has an external store with that name: {store.name}')
|
|
868
|
+
_logger.info(f'Linking external store `{store.name}` to table `{self.name}`')
|
|
831
869
|
self._tbl_version.link_external_store(store)
|
|
832
|
-
print(f'Linked external store `{store.name}` to table `{self.
|
|
870
|
+
print(f'Linked external store `{store.name}` to table `{self.name}`.')
|
|
833
871
|
|
|
834
872
|
def unlink_external_stores(
|
|
835
873
|
self,
|
|
@@ -861,11 +899,11 @@ class Table(SchemaObject):
|
|
|
861
899
|
if not ignore_errors:
|
|
862
900
|
for store in stores:
|
|
863
901
|
if store not in all_stores:
|
|
864
|
-
raise excs.Error(f'Table `{self.
|
|
902
|
+
raise excs.Error(f'Table `{self.name}` has no external store with that name: {store}')
|
|
865
903
|
|
|
866
904
|
for store in stores:
|
|
867
905
|
self._tbl_version.unlink_external_store(store, delete_external_data=delete_external_data)
|
|
868
|
-
print(f'Unlinked external store from table `{self.
|
|
906
|
+
print(f'Unlinked external store from table `{self.name}`: {store}')
|
|
869
907
|
|
|
870
908
|
def sync(
|
|
871
909
|
self,
|
|
@@ -893,7 +931,7 @@ class Table(SchemaObject):
|
|
|
893
931
|
|
|
894
932
|
for store in stores:
|
|
895
933
|
if store not in all_stores:
|
|
896
|
-
raise excs.Error(f'Table `{self.
|
|
934
|
+
raise excs.Error(f'Table `{self.name}` has no external store with that name: {store}')
|
|
897
935
|
|
|
898
936
|
from pixeltable.io import SyncStatus
|
|
899
937
|
|
|
@@ -540,39 +540,12 @@ class TableVersion:
|
|
|
540
540
|
num_rows=row_count, num_computed_values=row_count, num_excs=num_excs,
|
|
541
541
|
cols_with_excs=[f'{col.tbl.name}.{col.name}'for col in cols_with_excs if col.name is not None])
|
|
542
542
|
|
|
543
|
-
def drop_column(self,
|
|
543
|
+
def drop_column(self, col: Column) -> None:
|
|
544
544
|
"""Drop a column from the table.
|
|
545
545
|
"""
|
|
546
546
|
from pixeltable.catalog import Catalog
|
|
547
547
|
|
|
548
548
|
assert not self.is_snapshot
|
|
549
|
-
if name not in self.cols_by_name:
|
|
550
|
-
raise excs.Error(f'Unknown column: {name}')
|
|
551
|
-
col = self.cols_by_name[name]
|
|
552
|
-
dependent_user_cols = [c for c in col.dependent_cols if c.name is not None]
|
|
553
|
-
if len(dependent_user_cols) > 0:
|
|
554
|
-
raise excs.Error(
|
|
555
|
-
f'Cannot drop column `{name}` because the following columns depend on it:\n'
|
|
556
|
-
f'{", ".join(c.name for c in dependent_user_cols)}'
|
|
557
|
-
)
|
|
558
|
-
# See if this column has a dependent store. We need to look through all stores in all
|
|
559
|
-
# (transitive) views of this table.
|
|
560
|
-
transitive_views = Catalog.get().tbls[self.id].get_views(recursive=True)
|
|
561
|
-
dependent_stores = [
|
|
562
|
-
(view, store)
|
|
563
|
-
for view in transitive_views
|
|
564
|
-
for store in view._tbl_version.external_stores.values()
|
|
565
|
-
if col in store.get_local_columns()
|
|
566
|
-
]
|
|
567
|
-
if len(dependent_stores) > 0:
|
|
568
|
-
dependent_store_names = [
|
|
569
|
-
store.name if view._get_id() == self.id else f'{store.name} (in view `{view.get_name()}`)'
|
|
570
|
-
for view, store in dependent_stores
|
|
571
|
-
]
|
|
572
|
-
raise excs.Error(
|
|
573
|
-
f'Cannot drop column `{name}` because the following external stores depend on it:\n'
|
|
574
|
-
f'{", ".join(dependent_store_names)}'
|
|
575
|
-
)
|
|
576
549
|
|
|
577
550
|
# we're creating a new schema version
|
|
578
551
|
self.version += 1
|
|
@@ -596,7 +569,7 @@ class TableVersion:
|
|
|
596
569
|
del self.idxs_by_name[idx_name]
|
|
597
570
|
self._drop_columns(dropped_cols)
|
|
598
571
|
self._update_md(time.time(), conn, preceding_schema_version=preceding_schema_version)
|
|
599
|
-
_logger.info(f'Dropped column {name} from table {self.name}, new version: {self.version}')
|
|
572
|
+
_logger.info(f'Dropped column {col.name} from table {self.name}, new version: {self.version}')
|
|
600
573
|
|
|
601
574
|
def _drop_columns(self, cols: Iterable[Column]) -> None:
|
|
602
575
|
"""Mark columns as dropped"""
|
pixeltable/dataframe.py
CHANGED
|
@@ -558,7 +558,7 @@ class DataFrame:
|
|
|
558
558
|
# we need to make sure that the grouping table is a base of self.tbl
|
|
559
559
|
base = self.tbl.find_tbl_version(item._tbl_version_path.tbl_id())
|
|
560
560
|
if base is None or base.id == self.tbl.tbl_id():
|
|
561
|
-
raise excs.Error(f'group_by(): {item.
|
|
561
|
+
raise excs.Error(f'group_by(): {item.name} is not a base table of {self.tbl.tbl_name()}')
|
|
562
562
|
grouping_tbl = item._tbl_version_path.tbl_version
|
|
563
563
|
break
|
|
564
564
|
if not isinstance(item, exprs.Expr):
|
pixeltable/exprs/column_ref.py
CHANGED
|
@@ -63,14 +63,9 @@ class ColumnRef(Expr):
|
|
|
63
63
|
|
|
64
64
|
return super().__getattr__(name)
|
|
65
65
|
|
|
66
|
-
def similarity(self,
|
|
67
|
-
# if isinstance(other, Expr):
|
|
68
|
-
# raise excs.Error(f'similarity(): requires a string or a PIL.Image.Image object, not an expression')
|
|
69
|
-
item = Expr.from_object(other)
|
|
70
|
-
if item is None or not(item.col_type.is_string_type() or item.col_type.is_image_type()):
|
|
71
|
-
raise excs.Error(f'similarity(): requires a string or a PIL.Image.Image object, not a {type(other)}')
|
|
66
|
+
def similarity(self, item: Any, *, idx: Optional[str] = None) -> Expr:
|
|
72
67
|
from .similarity_expr import SimilarityExpr
|
|
73
|
-
return SimilarityExpr(self, item)
|
|
68
|
+
return SimilarityExpr(self, item, idx_name=idx)
|
|
74
69
|
|
|
75
70
|
def default_column_name(self) -> Optional[str]:
|
|
76
71
|
return str(self)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Optional, List
|
|
1
|
+
from typing import Optional, List, Any
|
|
2
2
|
|
|
3
3
|
import sqlalchemy as sql
|
|
4
4
|
import PIL.Image
|
|
@@ -14,33 +14,44 @@ from .row_builder import RowBuilder
|
|
|
14
14
|
|
|
15
15
|
class SimilarityExpr(Expr):
|
|
16
16
|
|
|
17
|
-
def __init__(self, col_ref: ColumnRef, item:
|
|
17
|
+
def __init__(self, col_ref: ColumnRef, item: Any, idx_name: Optional[str] = None):
|
|
18
18
|
super().__init__(ts.FloatType())
|
|
19
|
-
|
|
19
|
+
item_expr = Expr.from_object(item)
|
|
20
|
+
if item_expr is None or not(item_expr.col_type.is_string_type() or item_expr.col_type.is_image_type()):
|
|
21
|
+
raise excs.Error(f'similarity(): requires a string or a PIL.Image.Image object, not a {type(item)}')
|
|
22
|
+
assert item_expr.col_type.is_string_type() or item_expr.col_type.is_image_type()
|
|
23
|
+
|
|
24
|
+
self.components = [col_ref, item_expr]
|
|
20
25
|
self.id = self._create_id()
|
|
21
|
-
assert item.col_type.is_string_type() or item.col_type.is_image_type()
|
|
22
26
|
|
|
23
27
|
# determine index to use
|
|
24
28
|
idx_info = col_ref.col.get_idx_info()
|
|
25
29
|
import pixeltable.index as index
|
|
26
|
-
embedding_idx_info =
|
|
30
|
+
embedding_idx_info = {
|
|
31
|
+
info.name: info for info in idx_info.values() if isinstance(info.idx, index.EmbeddingIndex)
|
|
32
|
+
}
|
|
27
33
|
if len(embedding_idx_info) == 0:
|
|
28
|
-
raise excs.Error(f'No index found for column {col_ref.col}')
|
|
34
|
+
raise excs.Error(f'No index found for column {col_ref.col!r}')
|
|
35
|
+
if idx_name is not None and idx_name not in embedding_idx_info:
|
|
36
|
+
raise excs.Error(f'Index {idx_name!r} not found for column {col_ref.col.name!r}')
|
|
29
37
|
if len(embedding_idx_info) > 1:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
if idx_name is None:
|
|
39
|
+
raise excs.Error(
|
|
40
|
+
f'Column {col_ref.col.name!r} has multiple indices; use the index name to disambiguate: '
|
|
41
|
+
f'`{col_ref.col.name}.similarity(..., idx=<name>)`')
|
|
42
|
+
self.idx_info = embedding_idx_info[idx_name]
|
|
43
|
+
else:
|
|
44
|
+
self.idx_info = next(iter(embedding_idx_info.values()))
|
|
34
45
|
idx = self.idx_info.idx
|
|
35
46
|
|
|
36
|
-
if
|
|
47
|
+
if item_expr.col_type.is_string_type() and idx.string_embed is None:
|
|
37
48
|
raise excs.Error(
|
|
38
|
-
f'Embedding index {self.idx_info.name} on column {self.idx_info.col.name} was created without the '
|
|
39
|
-
f'
|
|
40
|
-
if
|
|
49
|
+
f'Embedding index {self.idx_info.name!r} on column {self.idx_info.col.name!r} was created without the '
|
|
50
|
+
f"'string_embed' parameter and does not support string queries")
|
|
51
|
+
if item_expr.col_type.is_image_type() and idx.image_embed is None:
|
|
41
52
|
raise excs.Error(
|
|
42
|
-
f'Embedding index {self.idx_info.name} on column {self.idx_info.col.name} was created without the '
|
|
43
|
-
f'
|
|
53
|
+
f'Embedding index {self.idx_info.name!r} on column {self.idx_info.col.name!r} was created without the '
|
|
54
|
+
f"'image_embed' parameter and does not support image queries")
|
|
44
55
|
|
|
45
56
|
def __str__(self) -> str:
|
|
46
57
|
return f'{self.components[0]}.similarity({self.components[1]})'
|
pixeltable/functions/openai.py
CHANGED
|
@@ -141,7 +141,7 @@ def chat_completions(
|
|
|
141
141
|
|
|
142
142
|
|
|
143
143
|
@pxt.udf
|
|
144
|
-
def vision(prompt: str, image: PIL.Image.Image, *, model: str
|
|
144
|
+
def vision(prompt: str, image: PIL.Image.Image, *, model: str) -> str:
|
|
145
145
|
# TODO(aaron-siegel): Decompose CPU/GPU ops into separate functions
|
|
146
146
|
bytes_arr = io.BytesIO()
|
|
147
147
|
image.save(bytes_arr, format='png')
|
pixeltable/globals.py
CHANGED
|
@@ -234,7 +234,7 @@ def drop_table(path: str, force: bool = False, ignore_errors: bool = False) -> N
|
|
|
234
234
|
|
|
235
235
|
Args:
|
|
236
236
|
path: Path to the table.
|
|
237
|
-
force:
|
|
237
|
+
force: If `True`, will also drop all views or sub-views of this table.
|
|
238
238
|
ignore_errors: Whether to ignore errors if the table does not exist.
|
|
239
239
|
|
|
240
240
|
Raises:
|
|
@@ -243,21 +243,27 @@ def drop_table(path: str, force: bool = False, ignore_errors: bool = False) -> N
|
|
|
243
243
|
Examples:
|
|
244
244
|
>>> cl.drop_table('my_table')
|
|
245
245
|
"""
|
|
246
|
+
cat = Catalog.get()
|
|
246
247
|
path_obj = catalog.Path(path)
|
|
247
248
|
try:
|
|
248
|
-
|
|
249
|
+
cat.paths.check_is_valid(path_obj, expected=catalog.Table)
|
|
249
250
|
except Exception as e:
|
|
250
|
-
if ignore_errors:
|
|
251
|
+
if ignore_errors or force:
|
|
251
252
|
_logger.info(f'Skipped table `{path}` (does not exist).')
|
|
252
253
|
return
|
|
253
254
|
else:
|
|
254
255
|
raise e
|
|
255
|
-
tbl =
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
256
|
+
tbl = cat.paths[path_obj]
|
|
257
|
+
assert isinstance(tbl, catalog.Table)
|
|
258
|
+
if len(cat.tbl_dependents[tbl._id]) > 0:
|
|
259
|
+
dependent_paths = [dep.path for dep in cat.tbl_dependents[tbl._id]]
|
|
260
|
+
if force:
|
|
261
|
+
for dependent_path in dependent_paths:
|
|
262
|
+
drop_table(dependent_path, force=True)
|
|
263
|
+
else:
|
|
264
|
+
raise excs.Error(f'Table {path} has dependents: {", ".join(dependent_paths)}')
|
|
259
265
|
tbl._drop()
|
|
260
|
-
del
|
|
266
|
+
del cat.paths[path_obj]
|
|
261
267
|
_logger.info(f'Dropped table `{path}`.')
|
|
262
268
|
|
|
263
269
|
|
|
@@ -291,7 +297,7 @@ def list_tables(dir_path: str = '', recursive: bool = True) -> list[str]:
|
|
|
291
297
|
return [str(p) for p in Catalog.get().paths.get_children(path, child_type=catalog.Table, recursive=recursive)]
|
|
292
298
|
|
|
293
299
|
|
|
294
|
-
def create_dir(path_str: str, ignore_errors: bool = False) ->
|
|
300
|
+
def create_dir(path_str: str, ignore_errors: bool = False) -> catalog.Dir:
|
|
295
301
|
"""Create a directory.
|
|
296
302
|
|
|
297
303
|
Args:
|
|
@@ -319,10 +325,12 @@ def create_dir(path_str: str, ignore_errors: bool = False) -> None:
|
|
|
319
325
|
session.add(dir_record)
|
|
320
326
|
session.flush()
|
|
321
327
|
assert dir_record.id is not None
|
|
322
|
-
|
|
328
|
+
dir = catalog.Dir(dir_record.id, parent._id, path.name)
|
|
329
|
+
Catalog.get().paths[path] = dir
|
|
323
330
|
session.commit()
|
|
324
331
|
_logger.info(f'Created directory `{path_str}`.')
|
|
325
332
|
print(f'Created directory `{path_str}`.')
|
|
333
|
+
return dir
|
|
326
334
|
except excs.Error as e:
|
|
327
335
|
if ignore_errors:
|
|
328
336
|
return
|
|
@@ -330,7 +338,7 @@ def create_dir(path_str: str, ignore_errors: bool = False) -> None:
|
|
|
330
338
|
raise e
|
|
331
339
|
|
|
332
340
|
|
|
333
|
-
def
|
|
341
|
+
def drop_dir(path_str: str, force: bool = False, ignore_errors: bool = False) -> None:
|
|
334
342
|
"""Remove a directory.
|
|
335
343
|
|
|
336
344
|
Args:
|
|
@@ -340,31 +348,49 @@ def rm_dir(path_str: str) -> None:
|
|
|
340
348
|
Error: If the path does not exist or does not designate a directory or if the directory is not empty.
|
|
341
349
|
|
|
342
350
|
Examples:
|
|
343
|
-
>>> cl.
|
|
351
|
+
>>> cl.drop_dir('my_dir')
|
|
344
352
|
|
|
345
353
|
Remove a subdirectory:
|
|
346
354
|
|
|
347
|
-
>>> cl.
|
|
355
|
+
>>> cl.drop_dir('my_dir.sub_dir')
|
|
348
356
|
"""
|
|
357
|
+
cat = Catalog.get()
|
|
349
358
|
path = catalog.Path(path_str)
|
|
350
|
-
Catalog.get().paths.check_is_valid(path, expected=catalog.Dir)
|
|
351
359
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
360
|
+
try:
|
|
361
|
+
cat.paths.check_is_valid(path, expected=catalog.Dir)
|
|
362
|
+
except Exception as e:
|
|
363
|
+
if ignore_errors or force:
|
|
364
|
+
_logger.info(f'Skipped directory `{path}` (does not exist).')
|
|
365
|
+
return
|
|
366
|
+
else:
|
|
367
|
+
raise e
|
|
368
|
+
|
|
369
|
+
children = cat.paths.get_children(path, child_type=None, recursive=True)
|
|
370
|
+
|
|
371
|
+
if len(children) > 0 and not force:
|
|
372
|
+
raise excs.Error(f'Directory `{path_str}` is not empty.')
|
|
373
|
+
|
|
374
|
+
for child in children:
|
|
375
|
+
assert isinstance(child, catalog.Path)
|
|
376
|
+
# We need to check that the child is still in `cat.paths`, since it is possible it was
|
|
377
|
+
# already deleted as a dependent of a preceding child in the iteration.
|
|
378
|
+
try:
|
|
379
|
+
obj = cat.paths[child]
|
|
380
|
+
except excs.Error:
|
|
381
|
+
continue
|
|
382
|
+
if isinstance(obj, catalog.Dir):
|
|
383
|
+
drop_dir(str(child), force=True)
|
|
384
|
+
else:
|
|
385
|
+
assert isinstance(obj, catalog.Table)
|
|
386
|
+
assert not obj._is_dropped # else it should have been removed from `cat.paths` already
|
|
387
|
+
drop_table(str(child), force=True)
|
|
362
388
|
|
|
363
389
|
with Env.get().engine.begin() as conn:
|
|
364
390
|
dir = Catalog.get().paths[path]
|
|
365
391
|
conn.execute(sql.delete(schema.Dir.__table__).where(schema.Dir.id == dir._id))
|
|
366
392
|
del Catalog.get().paths[path]
|
|
367
|
-
_logger.info(f'Removed directory {path_str}')
|
|
393
|
+
_logger.info(f'Removed directory `{path_str}`.')
|
|
368
394
|
|
|
369
395
|
|
|
370
396
|
def list_dirs(path_str: str = '', recursive: bool = True) -> list[str]:
|
|
@@ -416,28 +442,6 @@ def list_functions() -> pd.DataFrame:
|
|
|
416
442
|
return pd_df.hide(axis='index')
|
|
417
443
|
|
|
418
444
|
|
|
419
|
-
def get_path(schema_obj: catalog.SchemaObject) -> str:
|
|
420
|
-
"""Returns the path to a SchemaObject.
|
|
421
|
-
|
|
422
|
-
Args:
|
|
423
|
-
schema_obj: SchemaObject to get the path for.
|
|
424
|
-
|
|
425
|
-
Returns:
|
|
426
|
-
Path to the SchemaObject.
|
|
427
|
-
"""
|
|
428
|
-
path_elements: list[str] = []
|
|
429
|
-
dir_id = schema_obj._dir_id
|
|
430
|
-
while dir_id is not None:
|
|
431
|
-
dir = Catalog.get().paths.get_schema_obj(dir_id)
|
|
432
|
-
if dir._dir_id is None:
|
|
433
|
-
# this is the root dir with name '', which we don't want to include in the path
|
|
434
|
-
break
|
|
435
|
-
path_elements.insert(0, dir._name)
|
|
436
|
-
dir_id = dir._dir_id
|
|
437
|
-
path_elements.append(schema_obj._name)
|
|
438
|
-
return '.'.join(path_elements)
|
|
439
|
-
|
|
440
|
-
|
|
441
445
|
def configure_logging(
|
|
442
446
|
*,
|
|
443
447
|
to_stdout: Optional[bool] = None,
|
|
@@ -24,6 +24,7 @@ class EmbeddingIndex(IndexBase):
|
|
|
24
24
|
- similarity_clause() converts those metrics back to their original form; it is used in expressions outside
|
|
25
25
|
the Order By clause
|
|
26
26
|
- order_by_clause() is used exclusively in the ORDER BY clause
|
|
27
|
+
- embedding function parameters are named '<type-name>_embed', where type-name is ColumnType.Type.name
|
|
27
28
|
"""
|
|
28
29
|
|
|
29
30
|
class Metric(enum.Enum):
|
|
@@ -38,30 +39,30 @@ class EmbeddingIndex(IndexBase):
|
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
def __init__(
|
|
41
|
-
self, c: catalog.Column, metric: str,
|
|
42
|
-
|
|
42
|
+
self, c: catalog.Column, metric: str, string_embed: Optional[func.Function] = None,
|
|
43
|
+
image_embed: Optional[func.Function] = None):
|
|
43
44
|
metric_names = [m.name.lower() for m in self.Metric]
|
|
44
45
|
if metric.lower() not in metric_names:
|
|
45
46
|
raise excs.Error(f'Invalid metric {metric}, must be one of {metric_names}')
|
|
46
47
|
if not c.col_type.is_string_type() and not c.col_type.is_image_type():
|
|
47
48
|
raise excs.Error(f'Embedding index requires string or image column')
|
|
48
|
-
if c.col_type.is_string_type() and
|
|
49
|
-
raise excs.Error(f
|
|
50
|
-
if c.col_type.is_image_type() and
|
|
51
|
-
raise excs.Error(f
|
|
52
|
-
if
|
|
49
|
+
if c.col_type.is_string_type() and string_embed is None:
|
|
50
|
+
raise excs.Error(f"Text embedding function is required for column {c.name} (parameter 'string_embed')")
|
|
51
|
+
if c.col_type.is_image_type() and image_embed is None:
|
|
52
|
+
raise excs.Error(f"Image embedding function is required for column {c.name} (parameter 'image_embed')")
|
|
53
|
+
if string_embed is not None:
|
|
53
54
|
# verify signature
|
|
54
|
-
self._validate_embedding_fn(
|
|
55
|
-
if
|
|
55
|
+
self._validate_embedding_fn(string_embed, 'string_embed', ts.ColumnType.Type.STRING)
|
|
56
|
+
if image_embed is not None:
|
|
56
57
|
# verify signature
|
|
57
|
-
self._validate_embedding_fn(
|
|
58
|
+
self._validate_embedding_fn(image_embed, 'image_embed', ts.ColumnType.Type.IMAGE)
|
|
58
59
|
|
|
59
60
|
self.metric = self.Metric[metric.upper()]
|
|
60
61
|
from pixeltable.exprs import ColumnRef
|
|
61
|
-
self.value_expr =
|
|
62
|
+
self.value_expr = string_embed(ColumnRef(c)) if c.col_type.is_string_type() else image_embed(ColumnRef(c))
|
|
62
63
|
assert self.value_expr.col_type.is_array_type()
|
|
63
|
-
self.
|
|
64
|
-
self.
|
|
64
|
+
self.string_embed = string_embed
|
|
65
|
+
self.image_embed = image_embed
|
|
65
66
|
vector_size = self.value_expr.col_type.shape[0]
|
|
66
67
|
assert vector_size is not None
|
|
67
68
|
self.index_col_type = pgvector.sqlalchemy.Vector(vector_size)
|
|
@@ -88,14 +89,14 @@ class EmbeddingIndex(IndexBase):
|
|
|
88
89
|
idx.create(bind=conn)
|
|
89
90
|
|
|
90
91
|
def similarity_clause(self, val_column: catalog.Column, item: Any) -> sql.ClauseElement:
|
|
91
|
-
"""Create a ClauseElement
|
|
92
|
+
"""Create a ClauseElement that represents '<val_column> <op> <item>'"""
|
|
92
93
|
assert isinstance(item, (str, PIL.Image.Image))
|
|
93
94
|
if isinstance(item, str):
|
|
94
|
-
assert self.
|
|
95
|
-
embedding = self.
|
|
95
|
+
assert self.string_embed is not None
|
|
96
|
+
embedding = self.string_embed.exec(item)
|
|
96
97
|
if isinstance(item, PIL.Image.Image):
|
|
97
|
-
assert self.
|
|
98
|
-
embedding = self.
|
|
98
|
+
assert self.image_embed is not None
|
|
99
|
+
embedding = self.image_embed.exec(item)
|
|
99
100
|
|
|
100
101
|
if self.metric == self.Metric.COSINE:
|
|
101
102
|
return val_column.sa_col.cosine_distance(embedding) * -1 + 1
|
|
@@ -110,11 +111,11 @@ class EmbeddingIndex(IndexBase):
|
|
|
110
111
|
assert isinstance(item, (str, PIL.Image.Image))
|
|
111
112
|
embedding: Optional[np.ndarray] = None
|
|
112
113
|
if isinstance(item, str):
|
|
113
|
-
assert self.
|
|
114
|
-
embedding = self.
|
|
114
|
+
assert self.string_embed is not None
|
|
115
|
+
embedding = self.string_embed.exec(item)
|
|
115
116
|
if isinstance(item, PIL.Image.Image):
|
|
116
|
-
assert self.
|
|
117
|
-
embedding = self.
|
|
117
|
+
assert self.image_embed is not None
|
|
118
|
+
embedding = self.image_embed.exec(item)
|
|
118
119
|
assert embedding is not None
|
|
119
120
|
|
|
120
121
|
if self.metric == self.Metric.COSINE:
|
|
@@ -160,12 +161,12 @@ class EmbeddingIndex(IndexBase):
|
|
|
160
161
|
def as_dict(self) -> dict:
|
|
161
162
|
return {
|
|
162
163
|
'metric': self.metric.name.lower(),
|
|
163
|
-
'
|
|
164
|
-
'
|
|
164
|
+
'string_embed': None if self.string_embed is None else self.string_embed.as_dict(),
|
|
165
|
+
'image_embed': None if self.image_embed is None else self.image_embed.as_dict()
|
|
165
166
|
}
|
|
166
167
|
|
|
167
168
|
@classmethod
|
|
168
169
|
def from_dict(cls, c: catalog.Column, d: dict) -> EmbeddingIndex:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return cls(c, metric=d['metric'],
|
|
170
|
+
string_embed = func.Function.from_dict(d['string_embed']) if d['string_embed'] is not None else None
|
|
171
|
+
image_embed = func.Function.from_dict(d['image_embed']) if d['image_embed'] is not None else None
|
|
172
|
+
return cls(c, metric=d['metric'], string_embed=string_embed, image_embed=image_embed)
|
pixeltable/io/external_store.py
CHANGED
|
@@ -222,12 +222,12 @@ class Project(ExternalStore, abc.ABC):
|
|
|
222
222
|
if t_col not in t_cols:
|
|
223
223
|
if is_user_specified_col_mapping:
|
|
224
224
|
raise excs.Error(
|
|
225
|
-
f'Column name `{t_col}` appears as a key in `col_mapping`, but Table `{table.
|
|
225
|
+
f'Column name `{t_col}` appears as a key in `col_mapping`, but Table `{table.name}` '
|
|
226
226
|
'contains no such column.'
|
|
227
227
|
)
|
|
228
228
|
else:
|
|
229
229
|
raise excs.Error(
|
|
230
|
-
f'Column `{t_col}` does not exist in Table `{table.
|
|
230
|
+
f'Column `{t_col}` does not exist in Table `{table.name}`. Either add a column `{t_col}`, '
|
|
231
231
|
f'or specify a `col_mapping` to associate a different column with the external field `{ext_col}`.'
|
|
232
232
|
)
|
|
233
233
|
if ext_col not in export_cols and ext_col not in import_cols:
|
pixeltable/io/globals.py
CHANGED
|
@@ -50,7 +50,7 @@ def create_label_studio_project(
|
|
|
50
50
|
`ls_project_0`, `ls_project_1`, etc.
|
|
51
51
|
title: An optional title for the Label Studio project. This is the title that annotators
|
|
52
52
|
will see inside Label Studio. Unlike `name`, it does not need to be an identifier and
|
|
53
|
-
does not need to be unique. If not specified, the table name `t.
|
|
53
|
+
does not need to be unique. If not specified, the table name `t.name` will be used.
|
|
54
54
|
media_import_method: The method to use when transferring media files to Label Studio:
|
|
55
55
|
- `post`: Media will be sent to Label Studio via HTTP post. This should generally only be used for
|
|
56
56
|
prototyping; due to restrictions in Label Studio, it can only be used with projects that have
|
pixeltable/io/label_studio.py
CHANGED
|
@@ -95,7 +95,7 @@ class LabelStudioProject(Project):
|
|
|
95
95
|
return {ANNOTATIONS_COLUMN: pxt.JsonType(nullable=True)}
|
|
96
96
|
|
|
97
97
|
def sync(self, t: Table, export_data: bool, import_data: bool) -> SyncStatus:
|
|
98
|
-
_logger.info(f'Syncing Label Studio project "{self.project_title}" with table `{t.
|
|
98
|
+
_logger.info(f'Syncing Label Studio project "{self.project_title}" with table `{t.name}`'
|
|
99
99
|
f' (export: {export_data}, import: {import_data}).')
|
|
100
100
|
# Collect all existing tasks into a dict with entries `rowid: task`
|
|
101
101
|
tasks = {tuple(task['meta']['rowid']): task for task in self.__fetch_all_tasks()}
|
|
@@ -386,7 +386,7 @@ class LabelStudioProject(Project):
|
|
|
386
386
|
updates = [{'_rowid': rowid, local_annotations_col.name: ann} for rowid, ann in annotations.items()]
|
|
387
387
|
if len(updates) > 0:
|
|
388
388
|
_logger.info(
|
|
389
|
-
f'Updating table `{t.
|
|
389
|
+
f'Updating table `{t.name}`, column `{local_annotations_col.name}` with {len(updates)} total annotations.'
|
|
390
390
|
)
|
|
391
391
|
# batch_update currently doesn't propagate from views to base tables. As a workaround, we call
|
|
392
392
|
# batch_update on the actual ancestor table that holds the annotations column.
|
|
@@ -554,7 +554,7 @@ class LabelStudioProject(Project):
|
|
|
554
554
|
|
|
555
555
|
if title is None:
|
|
556
556
|
# `title` defaults to table name
|
|
557
|
-
title = t.
|
|
557
|
+
title = t.name
|
|
558
558
|
|
|
559
559
|
# Create a column to hold the annotations, if one does not yet exist
|
|
560
560
|
if col_mapping is None or ANNOTATIONS_COLUMN in col_mapping.values():
|
pixeltable/metadata/__init__.py
CHANGED
|
@@ -10,7 +10,7 @@ import sqlalchemy.orm as orm
|
|
|
10
10
|
from .schema import SystemInfo, SystemInfoMd
|
|
11
11
|
|
|
12
12
|
# current version of the metadata; this is incremented whenever the metadata schema changes
|
|
13
|
-
VERSION =
|
|
13
|
+
VERSION = 18
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def create_system_info(engine: sql.engine.Engine) -> None:
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import sqlalchemy as sql
|
|
2
|
+
|
|
3
|
+
from pixeltable.metadata import register_converter
|
|
4
|
+
from pixeltable.metadata.converters.util import convert_table_md
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@register_converter(version=17)
|
|
8
|
+
def _(engine: sql.engine.Engine) -> None:
|
|
9
|
+
convert_table_md(
|
|
10
|
+
engine,
|
|
11
|
+
table_md_updater=__update_table_md
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def __update_table_md(table_md: dict) -> None:
|
|
16
|
+
# key changes in IndexMd.init_args: img_embed -> image_embed, txt_embed -> string_embed
|
|
17
|
+
if len(table_md['index_md']) == 0:
|
|
18
|
+
return
|
|
19
|
+
for idx_md in table_md['index_md'].values():
|
|
20
|
+
if not idx_md['class_fqn'].endswith('.EmbeddingIndex'):
|
|
21
|
+
continue
|
|
22
|
+
init_dict = idx_md['init_args']
|
|
23
|
+
init_dict['image_embed'] = init_dict['img_embed']
|
|
24
|
+
del init_dict['img_embed']
|
|
25
|
+
init_dict['string_embed'] = init_dict['txt_embed']
|
|
26
|
+
del init_dict['txt_embed']
|
|
@@ -253,7 +253,7 @@ class Dumper:
|
|
|
253
253
|
add_column('c6_to_string', t.c6.apply(json.dumps))
|
|
254
254
|
add_column('c6_back_to_json', t[f'{col_prefix}_c6_to_string'].apply(json.loads))
|
|
255
255
|
|
|
256
|
-
t.add_embedding_index(f'{col_prefix}_function_call',
|
|
256
|
+
t.add_embedding_index(f'{col_prefix}_function_call', string_embed=embed_udf.clip_text_embed)
|
|
257
257
|
|
|
258
258
|
# query()
|
|
259
259
|
@t.query
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pixeltable
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.12
|
|
4
4
|
Summary: Pixeltable: The Multimodal AI Data Plane
|
|
5
|
-
Author:
|
|
6
|
-
Author-email:
|
|
5
|
+
Author: Pixeltable, Inc.
|
|
6
|
+
Author-email: contact@pixeltable.com
|
|
7
7
|
Requires-Python: >=3.9,<4.0
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.9
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
pixeltable/__init__.py,sha256=
|
|
2
|
-
pixeltable/__version__.py,sha256=
|
|
1
|
+
pixeltable/__init__.py,sha256=SkhQ6olglhj3NdcyVYzsTwpTZs8uVmtJa9INfsQV9gk,1267
|
|
2
|
+
pixeltable/__version__.py,sha256=VEuOm2X4I15fkc_I-vzJLLY4TEd1E8QfUbdSN8vRrVA,114
|
|
3
3
|
pixeltable/catalog/__init__.py,sha256=E41bxaPeQIcgRYzTWc2vkDOboQhRymrJf4IcHQO7o_8,453
|
|
4
4
|
pixeltable/catalog/catalog.py,sha256=8gsFWm6o9Qg4_BEO6oejdpmP4MAOlhmuKRaJP0o2UPU,7906
|
|
5
5
|
pixeltable/catalog/column.py,sha256=Dmc6CgFLExJy3tdvuX0Emjc8SgqZvmCbAHozibO1-G0,9417
|
|
@@ -9,12 +9,12 @@ pixeltable/catalog/insertable_table.py,sha256=u2yMCw1lWSIeRAknIKQmSMWS_3oLTn1kCR
|
|
|
9
9
|
pixeltable/catalog/named_function.py,sha256=UhHaimM_uJHS-0RQcqGOgvWeZtMfKsIgSeKSRwT2moU,1149
|
|
10
10
|
pixeltable/catalog/path.py,sha256=QgccEi_QOfaKt8YsR2zLtd_z7z7QQkU_1kprJFi2SPQ,1677
|
|
11
11
|
pixeltable/catalog/path_dict.py,sha256=xfvxg1Ze5jZCARUGASF2DRbQPh7pRVTYhuJ_u82gYUo,5941
|
|
12
|
-
pixeltable/catalog/schema_object.py,sha256=
|
|
13
|
-
pixeltable/catalog/table.py,sha256=
|
|
14
|
-
pixeltable/catalog/table_version.py,sha256=
|
|
12
|
+
pixeltable/catalog/schema_object.py,sha256=1GuxN68P3c7g0gmY8doB6qoUGJsalyECWaO-KEi96D0,1879
|
|
13
|
+
pixeltable/catalog/table.py,sha256=J4MRWMly9uz-utLnXIKh7OTUbY0t4_ogHeEuDcApEPk,41151
|
|
14
|
+
pixeltable/catalog/table_version.py,sha256=qnPIIxwIOQbukV84ydeksVNURb37kAnGOXI-ZO2kkCo,57233
|
|
15
15
|
pixeltable/catalog/table_version_path.py,sha256=6JZlgKMYa3Xf8p_2Z-iDIFIcfuYRyjbpc3_CC9l1HME,6396
|
|
16
16
|
pixeltable/catalog/view.py,sha256=3OAk-NBPlSagMCsdVtcx35jHD80SIYCuOy5dc1kM7Fs,10403
|
|
17
|
-
pixeltable/dataframe.py,sha256=
|
|
17
|
+
pixeltable/dataframe.py,sha256=7w-1-RGIGEJFJydFazHOzHLFSjZ4Ejvv_JjP4fKfRjo,34333
|
|
18
18
|
pixeltable/env.py,sha256=WO_WLfRj9Fft6QyW89S9cw47RTg1ALviStu9pNygJEQ,21635
|
|
19
19
|
pixeltable/exceptions.py,sha256=MSP9zeL0AmXT93XqjdvgGN4rzno1_KRrGriq6hpemnw,376
|
|
20
20
|
pixeltable/exec/__init__.py,sha256=RK7SKvrQ7Ky3G_LXDP4Bf7lHmMM_uYZl8dJaZYs0FjY,454
|
|
@@ -32,7 +32,7 @@ pixeltable/exprs/__init__.py,sha256=7dwrdk-NpF66OT-m5yNtFEhq-o1T476dnXHjluw2K1s,
|
|
|
32
32
|
pixeltable/exprs/arithmetic_expr.py,sha256=sWBYCBKI6IHj9ASwDcm2BlkQ5gleVtKtmpiPvzFNBJM,4386
|
|
33
33
|
pixeltable/exprs/array_slice.py,sha256=VmWc6iFusrM85MjyEBBCfXG1Jnt8-Gr6-J88BXxNoOE,2131
|
|
34
34
|
pixeltable/exprs/column_property_ref.py,sha256=0PHiBys0fxe2LgjaMId5UHob4E-ZggyPLnnW41RgA0E,2706
|
|
35
|
-
pixeltable/exprs/column_ref.py,sha256=
|
|
35
|
+
pixeltable/exprs/column_ref.py,sha256=rlw6Ic_atAfPZpEBNAqbRZauMeEUci2rDyVoHd1pA1I,5195
|
|
36
36
|
pixeltable/exprs/comparison.py,sha256=hP3M_lMWcFgENBICFosZPw2lRm1R6_qM_O9bKPmWJGI,4789
|
|
37
37
|
pixeltable/exprs/compound_predicate.py,sha256=Gh22MKi625m5A_RunVRd-a1XFi-fitikqBVz2VNXKrs,3830
|
|
38
38
|
pixeltable/exprs/data_row.py,sha256=RTBw1cBt29g_9g_hgdEYZ5aiHl7WZMBaBC2fOMOfwOc,8668
|
|
@@ -52,7 +52,7 @@ pixeltable/exprs/object_ref.py,sha256=eTcx84aWRI59fIiGvbdv3_cfL0XW4xEFQ4lwpLpJkM
|
|
|
52
52
|
pixeltable/exprs/predicate.py,sha256=OSDgjfSqiK7J_5GZMUXMvjfyomKEGi0JNxeB073SGXw,1859
|
|
53
53
|
pixeltable/exprs/row_builder.py,sha256=0OYd51J2ECPHkk2iN3MfYpS7LqnHTV5l5ubsVcy0dJA,15926
|
|
54
54
|
pixeltable/exprs/rowid_ref.py,sha256=74w4rEy21YysTVbyKNc3op-pYFqDAx8VJdtl7ZPpxHs,4268
|
|
55
|
-
pixeltable/exprs/similarity_expr.py,sha256=
|
|
55
|
+
pixeltable/exprs/similarity_expr.py,sha256=DqLOWtwPn9LxBRPm-d5Qz0yZ7w9YTOP8w0rgbr-6Lyg,3702
|
|
56
56
|
pixeltable/exprs/type_cast.py,sha256=JMg8p1qYoFfiAXfJPSbTEnfrK7lRO_JMaqlPHOrhNQU,1793
|
|
57
57
|
pixeltable/exprs/variable.py,sha256=Kg_O4ytcHYZFijIyMHYBJn063cTKU1-YE583FAz8Qaw,1361
|
|
58
58
|
pixeltable/ext/__init__.py,sha256=0uugfuME1FybVo-MdxaVNGagRjhcvNTnv5MZUem6Cyo,269
|
|
@@ -74,22 +74,22 @@ pixeltable/functions/fireworks.py,sha256=sbZy3HRn8o01nT4k1lOJJ_jGrjhBNkYmj1_Trao
|
|
|
74
74
|
pixeltable/functions/globals.py,sha256=MVKcwvfRaqBMV58KBxp5ACMsTbj29WD97AOg1N5ZheY,1596
|
|
75
75
|
pixeltable/functions/huggingface.py,sha256=qFdFpBX4R8Iz6fB0PKOwicdfvnEV7DQhtdcvsIQz55I,7372
|
|
76
76
|
pixeltable/functions/image.py,sha256=lC5PVvx0hXlINGcURLrLeTT7xUMXla6QUC1T9t4-A0Y,5440
|
|
77
|
-
pixeltable/functions/openai.py,sha256=
|
|
77
|
+
pixeltable/functions/openai.py,sha256=D0cDXe_zy1kUdKqM9T3qs7OBAUCrAINUy5P0DO0OSXc,7814
|
|
78
78
|
pixeltable/functions/string.py,sha256=Ae_weygd9Aj98buLC4tPLRYGg3LGSJEpXaqr93TF4nw,645
|
|
79
79
|
pixeltable/functions/together.py,sha256=2vHOoXMUIpeYwTYGTr3hDHePzy8zepvoeyORgV_9n34,4412
|
|
80
80
|
pixeltable/functions/util.py,sha256=F2iiIL7UfhYdCVzdCa3efYqWbaeLKFrbycKnuPkG57M,650
|
|
81
81
|
pixeltable/functions/video.py,sha256=yn52MimAVrSzUyAUtyxbd1RWveX_TyjwsomBuhK9V60,6516
|
|
82
82
|
pixeltable/functions/whisper.py,sha256=s7C4eV5tCJed-4Joob5LojGFEHPgapmT8awFPVxBKgQ,2199
|
|
83
|
-
pixeltable/globals.py,sha256=
|
|
83
|
+
pixeltable/globals.py,sha256=L_40LFK-wW5wJ8DtuLoeS2gCgm9rmwUjx5FLa5hMOmw,14828
|
|
84
84
|
pixeltable/index/__init__.py,sha256=XBwetNQQwnz0fiKwonOKhyy_U32l_cjt77kNvEIdjWs,102
|
|
85
85
|
pixeltable/index/base.py,sha256=YAQ5Dz1mfI0dfu9rxWHWroE8TjB90yKfPtXAzoADq38,1568
|
|
86
86
|
pixeltable/index/btree.py,sha256=NE4GYhcJWYJhdKyeHI0sQBlFvUaIgGOF9KLyCZOfFjE,1822
|
|
87
|
-
pixeltable/index/embedding_index.py,sha256=
|
|
87
|
+
pixeltable/index/embedding_index.py,sha256=U1wAjcTYvw3uJf3QHIOzBV8FLOUn8IeaFsLzUb_QTmc,7829
|
|
88
88
|
pixeltable/io/__init__.py,sha256=DdqOteR1Y-yRvFS0VojXHryBtIGzH8nAN-1MBj3LGRk,493
|
|
89
|
-
pixeltable/io/external_store.py,sha256=
|
|
90
|
-
pixeltable/io/globals.py,sha256=
|
|
89
|
+
pixeltable/io/external_store.py,sha256=owha7bEmA1ZvpZvBLBS6LHi9uLq1rUIkrMTGarsbjOU,16422
|
|
90
|
+
pixeltable/io/globals.py,sha256=v-L3ZQrjyutP_DHGXanymGjSJugWJ3STNUkzgylihOU,4540
|
|
91
91
|
pixeltable/io/hf_datasets.py,sha256=h5M1NkXOvEU8kaeT3AON1A18Vmhnc1lVo5a3TZ5AAic,8004
|
|
92
|
-
pixeltable/io/label_studio.py,sha256=
|
|
92
|
+
pixeltable/io/label_studio.py,sha256=yKCXPDZUev04O5r3tP5vrPpXe5KP4deQfbLHewNfVXQ,28764
|
|
93
93
|
pixeltable/io/pandas.py,sha256=cDHUDW2CGiBbsEJB9zE5vkXopTKxDdI-CZxNcp0OnIk,6478
|
|
94
94
|
pixeltable/io/parquet.py,sha256=i4hvYHsARe2GnZHxNmI66Vf3tr1sIFLN6KGCJYvH3o8,8149
|
|
95
95
|
pixeltable/iterators/__init__.py,sha256=sjldFckkT8aVRiKgEP6faeAK2NQBdzbmpwAeRhI1FkM,366
|
|
@@ -97,18 +97,19 @@ pixeltable/iterators/base.py,sha256=cnEh1tNN2JAxRzrLTg3dhun3N1oNQ8vifCm6ts3_UiE,
|
|
|
97
97
|
pixeltable/iterators/document.py,sha256=netSCJatG8NcgbHZ69BvQVICdAorQlYi8OlcpqwLQD4,19436
|
|
98
98
|
pixeltable/iterators/string.py,sha256=NG_fWc_GAITDfzl6MvrDOMrSoMcZdMZf6hPQztCSatE,1305
|
|
99
99
|
pixeltable/iterators/video.py,sha256=xtxODL1AfZwTfHVzWekhTCLA8gwTJIvJFdxC0KecD9Q,3836
|
|
100
|
-
pixeltable/metadata/__init__.py,sha256=
|
|
100
|
+
pixeltable/metadata/__init__.py,sha256=R4K9KSnefmvSCxXbBKTLAHD3QuHXgQ3a0wTs-eg94Os,2172
|
|
101
101
|
pixeltable/metadata/converters/convert_10.py,sha256=J1_r7LNNAWTdb042AwqFpJ4sEB-i4qhUdk5iOjcZk34,719
|
|
102
102
|
pixeltable/metadata/converters/convert_12.py,sha256=Ci-qyZW1gqci-8wnjeOB5afdq7KTuN-hVSV9OqSPx8g,162
|
|
103
103
|
pixeltable/metadata/converters/convert_13.py,sha256=yFR6lD3pOrZ46ZQBFKYvxiIYa7rRxh46Bsq7yiCBNak,1356
|
|
104
104
|
pixeltable/metadata/converters/convert_14.py,sha256=o4Dwu5wujJYILN-2chg3xCSUsh4cnn0sImv6rc75rSM,388
|
|
105
105
|
pixeltable/metadata/converters/convert_15.py,sha256=N-Lt3OdOrUprN-z1gFcxniZgAtZ7jzup_YUZzXX6EtY,1709
|
|
106
106
|
pixeltable/metadata/converters/convert_16.py,sha256=SvcWOYgLwRw_gLTnLbCSI9f2cpdkXazYOmmtJUOOzv4,476
|
|
107
|
+
pixeltable/metadata/converters/convert_17.py,sha256=vJg4y2lg53WSj9OSntWsdUiCr6yRgMQm0eFbs_Geqjg,861
|
|
107
108
|
pixeltable/metadata/converters/util.py,sha256=AcYs3yUICl93y8whf0pkeWZoCzE4JuUMafmcYMyJUCY,2618
|
|
108
109
|
pixeltable/metadata/schema.py,sha256=WJZ1YPgS88rFElXbjYgDhcrI4VReR1I9VPOnTkoHvoI,8418
|
|
109
110
|
pixeltable/plan.py,sha256=MXWgwQXD40GB57xQiq_wjXF3OL0XTEjjhQslMfFTt3w,32831
|
|
110
111
|
pixeltable/store.py,sha256=UDn-UMYuL6dTUym3yFsVhv9hUtnP_QtzhDJzsFInApc,18853
|
|
111
|
-
pixeltable/tool/create_test_db_dump.py,sha256=
|
|
112
|
+
pixeltable/tool/create_test_db_dump.py,sha256=iaMfBEyGHSMhhOJDyR0M9Idj9HkNgeTjmYLVhScjMZA,10729
|
|
112
113
|
pixeltable/tool/create_test_video.py,sha256=OLfccymYReIpzE8osZn4rQvLXxxiPC_l0vc06U74hVM,2899
|
|
113
114
|
pixeltable/tool/embed_udf.py,sha256=llHUhjGnCMp7Wyz7eHgKZV2v6o2ZWSgLQKscESuHK_o,269
|
|
114
115
|
pixeltable/type_system.py,sha256=oXnDVoP90ic6WSTF_DcgWDLx0MYKEU0ggGTesAKahic,29505
|
|
@@ -126,7 +127,7 @@ pixeltable/utils/pytorch.py,sha256=BR4tgfUWw-2rwWTOgzXj5qdMBpe1Arpp5SK4ax6jjpk,3
|
|
|
126
127
|
pixeltable/utils/s3.py,sha256=rkanuhk9DWvSfmbOLQW1j1Iov4sl2KhxGGKN-AJ8LSE,432
|
|
127
128
|
pixeltable/utils/sql.py,sha256=5n5_OmXAGtqFdL6z5XvgnU-vlx6Ba6f1WJrO1ZwUle8,765
|
|
128
129
|
pixeltable/utils/transactional_directory.py,sha256=UGzCrGtLR3hEEf8sYGuWBzLVFAEQml3vdIavigWeTBM,1349
|
|
129
|
-
pixeltable-0.2.
|
|
130
|
-
pixeltable-0.2.
|
|
131
|
-
pixeltable-0.2.
|
|
132
|
-
pixeltable-0.2.
|
|
130
|
+
pixeltable-0.2.12.dist-info/LICENSE,sha256=0UNMmwuqWPC0xDY1NWMm4uNJ2_MyA1pnTNRgQTvuBiQ,746
|
|
131
|
+
pixeltable-0.2.12.dist-info/METADATA,sha256=oVeTMu4HQQFxqj4AWPpiZiNPs9O5IUzxlBBHazAInJ0,9820
|
|
132
|
+
pixeltable-0.2.12.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
133
|
+
pixeltable-0.2.12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|