pixeltable 0.3.5__tar.gz → 0.3.6__tar.gz
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-0.3.5 → pixeltable-0.3.6}/PKG-INFO +1 -1
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/__version__.py +2 -2
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/table.py +2 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/dataframe.py +1 -1
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/data_row.py +4 -4
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/json_mapper.py +25 -8
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/json_path.py +6 -5
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/object_ref.py +16 -5
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/row_builder.py +10 -3
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/tools.py +26 -26
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/anthropic.py +9 -3
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/openai.py +7 -4
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pyproject.toml +1 -1
- {pixeltable-0.3.5 → pixeltable-0.3.6}/LICENSE +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/README.md +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/catalog.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/column.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/dir.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/globals.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/insertable_table.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/named_function.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/path.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/path_dict.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/schema_object.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/table_version.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/table_version_path.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/catalog/view.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/env.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exceptions.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/aggregation_node.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/cache_prefetch_node.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/component_iteration_node.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/data_row_batch.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/exec_context.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/exec_node.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/expr_eval/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/expr_eval/evaluators.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/expr_eval/expr_eval_node.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/expr_eval/globals.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/expr_eval/row_buffer.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/expr_eval/schedulers.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/in_memory_data_node.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/row_update_node.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exec/sql_node.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/arithmetic_expr.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/array_slice.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/column_property_ref.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/column_ref.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/comparison.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/compound_predicate.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/expr.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/expr_dict.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/expr_set.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/function_call.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/globals.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/in_predicate.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/inline_expr.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/is_null.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/literal.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/method_ref.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/rowid_ref.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/similarity_expr.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/sql_element_cache.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/type_cast.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/exprs/variable.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/ext/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/ext/functions/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/ext/functions/whisperx.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/ext/functions/yolox.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/aggregate_function.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/callable_function.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/expr_template_function.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/function.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/function_registry.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/globals.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/query_template_function.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/signature.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/func/udf.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/audio.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/deepseek.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/fireworks.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/gemini.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/globals.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/huggingface.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/image.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/json.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/llama_cpp.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/math.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/mistralai.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/ollama.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/replicate.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/string.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/timestamp.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/together.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/util.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/video.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/vision.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/functions/whisper.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/globals.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/index/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/index/base.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/index/btree.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/index/embedding_index.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/io/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/io/external_store.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/io/fiftyone.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/io/globals.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/io/hf_datasets.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/io/label_studio.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/io/pandas.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/io/parquet.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/io/utils.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/iterators/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/iterators/audio.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/iterators/base.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/iterators/document.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/iterators/image.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/iterators/string.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/iterators/video.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_10.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_12.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_13.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_14.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_15.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_16.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_17.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_18.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_19.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_20.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_21.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_22.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_23.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_24.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_25.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_26.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_27.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_28.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/convert_29.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/converters/util.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/notes.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/metadata/schema.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/plan.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/py.typed +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/share/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/share/packager.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/share/publish.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/store.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/type_system.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/__init__.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/arrow.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/coco.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/code.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/console_output.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/description_helper.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/documents.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/filecache.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/formatter.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/http_server.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/iceberg.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/media_store.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/pytorch.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/s3.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/sql.py +0 -0
- {pixeltable-0.3.5 → pixeltable-0.3.6}/pixeltable/utils/transactional_directory.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pixeltable
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: AI Data Infrastructure: Declarative, Multimodal, and Incremental
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Keywords: data-science,machine-learning,database,ai,computer-vision,chatbot,ml,artificial-intelligence,feature-engineering,multimodal,mlops,feature-store,vector-database,llm,genai
|
|
@@ -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.6'
|
|
3
|
+
__version_tuple__ = (0, 3, 6)
|
|
@@ -682,6 +682,7 @@ class Table(SchemaObject):
|
|
|
682
682
|
elif isinstance(spec, exprs.Expr):
|
|
683
683
|
# create copy so we can modify it
|
|
684
684
|
value_expr = spec.copy()
|
|
685
|
+
value_expr.bind_rel_paths()
|
|
685
686
|
elif isinstance(spec, dict):
|
|
686
687
|
cls._validate_column_spec(name, spec)
|
|
687
688
|
if 'type' in spec:
|
|
@@ -692,6 +693,7 @@ class Table(SchemaObject):
|
|
|
692
693
|
if value_expr is not None and isinstance(value_expr, exprs.Expr):
|
|
693
694
|
# create copy so we can modify it
|
|
694
695
|
value_expr = value_expr.copy()
|
|
696
|
+
value_expr.bind_rel_paths()
|
|
695
697
|
stored = spec.get('stored', True)
|
|
696
698
|
primary_key = spec.get('primary_key')
|
|
697
699
|
media_validation_str = spec.get('media_validation')
|
|
@@ -142,13 +142,13 @@ class DataRow:
|
|
|
142
142
|
self.file_paths[slot_idx] = None
|
|
143
143
|
self.file_urls[slot_idx] = None
|
|
144
144
|
|
|
145
|
-
def __getitem__(self, index:
|
|
145
|
+
def __getitem__(self, index: int) -> Any:
|
|
146
146
|
"""Returns in-memory value, ie, what is needed for expr evaluation"""
|
|
147
147
|
assert isinstance(index, int)
|
|
148
148
|
if not self.has_val[index]:
|
|
149
|
-
#
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
# This is a sufficiently cheap and sensitive validation that it makes sense to keep the assertion around
|
|
150
|
+
# even if python is running with -O.
|
|
151
|
+
raise AssertionError(index)
|
|
152
152
|
|
|
153
153
|
if self.file_urls[index] is not None and index in self.img_slot_idxs:
|
|
154
154
|
# if we need to load this from a file, it should have been materialized locally
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Optional
|
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
|
4
4
|
|
|
5
5
|
import sqlalchemy as sql
|
|
6
6
|
|
|
@@ -11,6 +11,9 @@ from .expr import _GLOBAL_SCOPE, Expr, ExprScope
|
|
|
11
11
|
from .row_builder import RowBuilder
|
|
12
12
|
from .sql_element_cache import SqlElementCache
|
|
13
13
|
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from .object_ref import ObjectRef
|
|
16
|
+
|
|
14
17
|
|
|
15
18
|
class JsonMapper(Expr):
|
|
16
19
|
"""
|
|
@@ -19,6 +22,10 @@ class JsonMapper(Expr):
|
|
|
19
22
|
is populated by JsonMapper.eval(). The JsonMapper effectively creates a new scope for its target expr.
|
|
20
23
|
"""
|
|
21
24
|
|
|
25
|
+
target_expr_scope: ExprScope
|
|
26
|
+
parent_mapper: Optional[JsonMapper]
|
|
27
|
+
target_expr_eval_ctx: Optional[RowBuilder.EvalCtx]
|
|
28
|
+
|
|
22
29
|
def __init__(self, src_expr: Expr, target_expr: Expr):
|
|
23
30
|
# TODO: type spec should be list[target_expr.col_type]
|
|
24
31
|
super().__init__(ts.JsonType())
|
|
@@ -29,12 +36,18 @@ class JsonMapper(Expr):
|
|
|
29
36
|
|
|
30
37
|
from .object_ref import ObjectRef
|
|
31
38
|
|
|
32
|
-
|
|
33
|
-
self.
|
|
34
|
-
self.
|
|
35
|
-
|
|
39
|
+
self.components = [src_expr, target_expr]
|
|
40
|
+
self.parent_mapper = None
|
|
41
|
+
self.target_expr_eval_ctx = None
|
|
42
|
+
|
|
43
|
+
# Intentionally create the id now, before adding the scope anchor; this ensures that JsonMappers will
|
|
44
|
+
# be recognized as equal so long as they have the same src_expr and target_expr.
|
|
45
|
+
# TODO: Might this cause problems after certain substitutions?
|
|
36
46
|
self.id = self._create_id()
|
|
37
47
|
|
|
48
|
+
scope_anchor = ObjectRef(self.target_expr_scope, self)
|
|
49
|
+
self.components.append(scope_anchor)
|
|
50
|
+
|
|
38
51
|
def bind_rel_paths(self, mapper: Optional[JsonMapper] = None) -> None:
|
|
39
52
|
self._src_expr.bind_rel_paths(mapper)
|
|
40
53
|
self._target_expr.bind_rel_paths(self)
|
|
@@ -84,8 +97,12 @@ class JsonMapper(Expr):
|
|
|
84
97
|
return self.components[1]
|
|
85
98
|
|
|
86
99
|
@property
|
|
87
|
-
def scope_anchor(self) ->
|
|
88
|
-
|
|
100
|
+
def scope_anchor(self) -> 'ObjectRef':
|
|
101
|
+
from .object_ref import ObjectRef
|
|
102
|
+
|
|
103
|
+
result = self.components[2]
|
|
104
|
+
assert isinstance(result, ObjectRef)
|
|
105
|
+
return result
|
|
89
106
|
|
|
90
107
|
def _equals(self, _: JsonMapper) -> bool:
|
|
91
108
|
return True
|
|
@@ -107,7 +124,7 @@ class JsonMapper(Expr):
|
|
|
107
124
|
for i, val in enumerate(src):
|
|
108
125
|
data_row[self.scope_anchor.slot_idx] = val
|
|
109
126
|
# stored target_expr
|
|
110
|
-
row_builder.eval(data_row, self.target_expr_eval_ctx)
|
|
127
|
+
row_builder.eval(data_row, self.target_expr_eval_ctx, force_eval=self._target_expr.scope())
|
|
111
128
|
result[i] = data_row[self._target_expr.slot_idx]
|
|
112
129
|
data_row[self.slot_idx] = result
|
|
113
130
|
|
|
@@ -43,11 +43,11 @@ class JsonPath(Expr):
|
|
|
43
43
|
self.id = self._create_id()
|
|
44
44
|
|
|
45
45
|
def __repr__(self) -> str:
|
|
46
|
-
# else
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
)
|
|
46
|
+
# else 'R': the anchor is RELATIVE_PATH_ROOT
|
|
47
|
+
anchor_str = str(self._anchor) if self._anchor is not None else 'R'
|
|
48
|
+
if len(self.path_elements) == 0:
|
|
49
|
+
return anchor_str
|
|
50
|
+
return f'{anchor_str}{"." if isinstance(self.path_elements[0], str) else ""}{self._json_path()}'
|
|
51
51
|
|
|
52
52
|
def _as_dict(self) -> dict:
|
|
53
53
|
path_elements = [[el.start, el.stop, el.step] if isinstance(el, slice) else el for el in self.path_elements]
|
|
@@ -158,6 +158,7 @@ class JsonPath(Expr):
|
|
|
158
158
|
return ''.join(result)
|
|
159
159
|
|
|
160
160
|
def eval(self, data_row: DataRow, row_builder: RowBuilder) -> None:
|
|
161
|
+
assert self._anchor is not None, self
|
|
161
162
|
val = data_row[self._anchor.slot_idx]
|
|
162
163
|
if self.compiled_path is not None:
|
|
163
164
|
val = self.compiled_path.search(val)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Optional
|
|
3
|
+
from typing import Any, Optional
|
|
4
4
|
|
|
5
5
|
import sqlalchemy as sql
|
|
6
6
|
|
|
@@ -26,14 +26,22 @@ class ObjectRef(Expr):
|
|
|
26
26
|
self.owner = owner
|
|
27
27
|
self.id = self._create_id()
|
|
28
28
|
|
|
29
|
+
def _id_attrs(self) -> list[tuple[str, Any]]:
|
|
30
|
+
# We have no components, so we can't rely on the default behavior here (otherwise, all ObjectRef
|
|
31
|
+
# instances will be conflated into a single slot).
|
|
32
|
+
return [('addr', id(self))]
|
|
33
|
+
|
|
34
|
+
def substitute(self, subs: dict[Expr, Expr]) -> Expr:
|
|
35
|
+
# Just return self; we need to avoid creating a new id after doing the substitution, because otherwise
|
|
36
|
+
# we'll wind up in a situation where the scope_anchor of the enclosing JsonMapper is different from the
|
|
37
|
+
# nested ObjectRefs inside its target_expr (and therefore occupies a different slot_idx).
|
|
38
|
+
return self
|
|
39
|
+
|
|
29
40
|
def scope(self) -> ExprScope:
|
|
30
41
|
return self._scope
|
|
31
42
|
|
|
32
|
-
def __str__(self) -> str:
|
|
33
|
-
assert False
|
|
34
|
-
|
|
35
43
|
def _equals(self, other: ObjectRef) -> bool:
|
|
36
|
-
return self.
|
|
44
|
+
return self.id == other.id
|
|
37
45
|
|
|
38
46
|
def sql_expr(self, _: SqlElementCache) -> Optional[sql.ColumnElement]:
|
|
39
47
|
return None
|
|
@@ -41,3 +49,6 @@ class ObjectRef(Expr):
|
|
|
41
49
|
def eval(self, data_row: DataRow, row_builder: RowBuilder) -> None:
|
|
42
50
|
# this will be called, but the value has already been materialized elsewhere
|
|
43
51
|
pass
|
|
52
|
+
|
|
53
|
+
def __repr__(self) -> str:
|
|
54
|
+
return f'ObjectRef({self.owner}, {self.id}, {self.owner.id})'
|
|
@@ -17,7 +17,7 @@ from pixeltable.env import Env
|
|
|
17
17
|
from pixeltable.utils.media_store import MediaStore
|
|
18
18
|
|
|
19
19
|
from .data_row import DataRow
|
|
20
|
-
from .expr import Expr
|
|
20
|
+
from .expr import Expr, ExprScope
|
|
21
21
|
from .expr_set import ExprSet
|
|
22
22
|
|
|
23
23
|
|
|
@@ -299,6 +299,7 @@ class RowBuilder:
|
|
|
299
299
|
# this is input and therefore doesn't depend on other exprs
|
|
300
300
|
continue
|
|
301
301
|
for d in expr.dependencies():
|
|
302
|
+
assert d.slot_idx is not None, f'{expr}, {d}'
|
|
302
303
|
if d.slot_idx in excluded_slot_idxs:
|
|
303
304
|
continue
|
|
304
305
|
dependencies[expr.slot_idx].add(d.slot_idx)
|
|
@@ -376,7 +377,12 @@ class RowBuilder:
|
|
|
376
377
|
data_row.set_exc(slot_idx, exc)
|
|
377
378
|
|
|
378
379
|
def eval(
|
|
379
|
-
self,
|
|
380
|
+
self,
|
|
381
|
+
data_row: DataRow,
|
|
382
|
+
ctx: EvalCtx,
|
|
383
|
+
profile: Optional[ExecProfile] = None,
|
|
384
|
+
ignore_errors: bool = False,
|
|
385
|
+
force_eval: Optional[ExprScope] = None,
|
|
380
386
|
) -> None:
|
|
381
387
|
"""
|
|
382
388
|
Populates the slots in data_row given in ctx.
|
|
@@ -384,10 +390,11 @@ class RowBuilder:
|
|
|
384
390
|
and omits any of that expr's dependents's eval().
|
|
385
391
|
profile: if present, populated with execution time of each expr.eval() call; indexed by expr.slot_idx
|
|
386
392
|
ignore_errors: if False, raises ExprEvalError if any expr.eval() raises an exception
|
|
393
|
+
force_eval: forces exprs in the specified scope to be reevaluated, even if they already have a value
|
|
387
394
|
"""
|
|
388
395
|
for expr in ctx.exprs:
|
|
389
396
|
assert expr.slot_idx >= 0
|
|
390
|
-
if data_row.has_val[expr.slot_idx] or data_row.has_exc(expr.slot_idx):
|
|
397
|
+
if expr.scope() != force_eval and (data_row.has_val[expr.slot_idx] or data_row.has_exc(expr.slot_idx)):
|
|
391
398
|
continue
|
|
392
399
|
try:
|
|
393
400
|
start_time = time.perf_counter()
|
|
@@ -48,22 +48,27 @@ class Tool(pydantic.BaseModel):
|
|
|
48
48
|
'additionalProperties': False, # TODO Handle kwargs?
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
# `tool_calls` must be in standardized tool invocation format:
|
|
52
|
-
# {tool_name: {'args': {name1: value1, name2: value2, ...}}, ...}
|
|
53
|
-
def invoke(self, tool_calls: 'exprs.Expr') -> 'exprs.
|
|
54
|
-
|
|
55
|
-
return self.fn(**kwargs)
|
|
51
|
+
# The output of `tool_calls` must be a dict in standardized tool invocation format:
|
|
52
|
+
# {tool_name: [{'args': {name1: value1, name2: value2, ...}}, ...], ...}
|
|
53
|
+
def invoke(self, tool_calls: 'exprs.Expr') -> 'exprs.Expr':
|
|
54
|
+
from pixeltable import exprs
|
|
56
55
|
|
|
57
|
-
def __extract_tool_arg(self, param: Parameter, tool_calls: 'exprs.Expr') -> 'exprs.Expr':
|
|
58
56
|
func_name = self.name or self.fn.name
|
|
57
|
+
return exprs.JsonMapper(tool_calls[func_name]['*'], self.__invoke_kwargs(exprs.RELATIVE_PATH_ROOT.args))
|
|
58
|
+
|
|
59
|
+
def __invoke_kwargs(self, kwargs: 'exprs.Expr') -> 'exprs.FunctionCall':
|
|
60
|
+
kwargs = {param.name: self.__extract_tool_arg(param, kwargs) for param in self.parameters.values()}
|
|
61
|
+
return self.fn(**kwargs)
|
|
62
|
+
|
|
63
|
+
def __extract_tool_arg(self, param: Parameter, kwargs: 'exprs.Expr') -> 'exprs.FunctionCall':
|
|
59
64
|
if param.col_type.is_string_type():
|
|
60
|
-
return _extract_str_tool_arg(
|
|
65
|
+
return _extract_str_tool_arg(kwargs, param_name=param.name)
|
|
61
66
|
if param.col_type.is_int_type():
|
|
62
|
-
return _extract_int_tool_arg(
|
|
67
|
+
return _extract_int_tool_arg(kwargs, param_name=param.name)
|
|
63
68
|
if param.col_type.is_float_type():
|
|
64
|
-
return _extract_float_tool_arg(
|
|
69
|
+
return _extract_float_tool_arg(kwargs, param_name=param.name)
|
|
65
70
|
if param.col_type.is_bool_type():
|
|
66
|
-
return _extract_bool_tool_arg(
|
|
71
|
+
return _extract_bool_tool_arg(kwargs, param_name=param.name)
|
|
67
72
|
assert False
|
|
68
73
|
|
|
69
74
|
|
|
@@ -113,34 +118,29 @@ class Tools(pydantic.BaseModel):
|
|
|
113
118
|
|
|
114
119
|
|
|
115
120
|
@udf
|
|
116
|
-
def _extract_str_tool_arg(
|
|
117
|
-
return _extract_arg(str,
|
|
121
|
+
def _extract_str_tool_arg(kwargs: dict[str, Any], param_name: str) -> Optional[str]:
|
|
122
|
+
return _extract_arg(str, kwargs, param_name)
|
|
118
123
|
|
|
119
124
|
|
|
120
125
|
@udf
|
|
121
|
-
def _extract_int_tool_arg(
|
|
122
|
-
return _extract_arg(int,
|
|
126
|
+
def _extract_int_tool_arg(kwargs: dict[str, Any], param_name: str) -> Optional[int]:
|
|
127
|
+
return _extract_arg(int, kwargs, param_name)
|
|
123
128
|
|
|
124
129
|
|
|
125
130
|
@udf
|
|
126
|
-
def _extract_float_tool_arg(
|
|
127
|
-
return _extract_arg(float,
|
|
131
|
+
def _extract_float_tool_arg(kwargs: dict[str, Any], param_name: str) -> Optional[float]:
|
|
132
|
+
return _extract_arg(float, kwargs, param_name)
|
|
128
133
|
|
|
129
134
|
|
|
130
135
|
@udf
|
|
131
|
-
def _extract_bool_tool_arg(
|
|
132
|
-
return _extract_arg(bool,
|
|
136
|
+
def _extract_bool_tool_arg(kwargs: dict[str, Any], param_name: str) -> Optional[bool]:
|
|
137
|
+
return _extract_arg(bool, kwargs, param_name)
|
|
133
138
|
|
|
134
139
|
|
|
135
140
|
T = TypeVar('T')
|
|
136
141
|
|
|
137
142
|
|
|
138
|
-
def _extract_arg(
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if func_name in tool_calls:
|
|
142
|
-
arguments = tool_calls[func_name]['args']
|
|
143
|
-
if param_name in arguments:
|
|
144
|
-
return eval_fn(arguments[param_name])
|
|
145
|
-
return None
|
|
143
|
+
def _extract_arg(eval_fn: Callable[[Any], T], kwargs: dict[str, Any], param_name: str) -> Optional[T]:
|
|
144
|
+
if param_name in kwargs:
|
|
145
|
+
return eval_fn(kwargs[param_name])
|
|
146
146
|
return None
|
|
@@ -213,9 +213,15 @@ def invoke_tools(tools: Tools, response: exprs.Expr) -> exprs.InlineDict:
|
|
|
213
213
|
@pxt.udf
|
|
214
214
|
def _anthropic_response_to_pxt_tool_calls(response: dict) -> Optional[dict]:
|
|
215
215
|
anthropic_tool_calls = [r for r in response['content'] if r['type'] == 'tool_use']
|
|
216
|
-
if len(anthropic_tool_calls)
|
|
217
|
-
return
|
|
218
|
-
|
|
216
|
+
if len(anthropic_tool_calls) == 0:
|
|
217
|
+
return None
|
|
218
|
+
pxt_tool_calls: dict[str, list[dict[str, Any]]] = {}
|
|
219
|
+
for tool_call in anthropic_tool_calls:
|
|
220
|
+
tool_name = tool_call['name']
|
|
221
|
+
if tool_name not in pxt_tool_calls:
|
|
222
|
+
pxt_tool_calls[tool_name] = []
|
|
223
|
+
pxt_tool_calls[tool_name].append({'args': tool_call['input']})
|
|
224
|
+
return pxt_tool_calls
|
|
219
225
|
|
|
220
226
|
|
|
221
227
|
_T = TypeVar('_T')
|
|
@@ -816,10 +816,13 @@ def _openai_response_to_pxt_tool_calls(response: dict) -> Optional[dict]:
|
|
|
816
816
|
if 'tool_calls' not in response['choices'][0]['message'] or response['choices'][0]['message']['tool_calls'] is None:
|
|
817
817
|
return None
|
|
818
818
|
openai_tool_calls = response['choices'][0]['message']['tool_calls']
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
819
|
+
pxt_tool_calls: dict[str, list[dict[str, Any]]] = {}
|
|
820
|
+
for tool_call in openai_tool_calls:
|
|
821
|
+
tool_name = tool_call['function']['name']
|
|
822
|
+
if tool_name not in pxt_tool_calls:
|
|
823
|
+
pxt_tool_calls[tool_name] = []
|
|
824
|
+
pxt_tool_calls[tool_name].append({'args': json.loads(tool_call['function']['arguments'])})
|
|
825
|
+
return pxt_tool_calls
|
|
823
826
|
|
|
824
827
|
|
|
825
828
|
_T = TypeVar('_T')
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|