pixeltable 0.3.5__py3-none-any.whl → 0.3.6__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 CHANGED
@@ -1,3 +1,3 @@
1
1
  # These version placeholders will be replaced during build.
2
- __version__ = '0.3.5'
3
- __version_tuple__ = (0, 3, 5)
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')
pixeltable/dataframe.py CHANGED
@@ -293,7 +293,7 @@ class DataFrame:
293
293
  group_by_clause = self.group_by_clause
294
294
 
295
295
  for item in self._select_list_exprs:
296
- item.bind_rel_paths(None)
296
+ item.bind_rel_paths()
297
297
 
298
298
  return plan.Planner.create_query_plan(
299
299
  self._from_clause,
@@ -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: object) -> Any:
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
- # for debugging purposes
150
- pass
151
- assert self.has_val[index], index
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
- scope_anchor = ObjectRef(self.target_expr_scope, self)
33
- self.components = [src_expr, target_expr, scope_anchor]
34
- self.parent_mapper: Optional[JsonMapper] = None
35
- self.target_expr_eval_ctx: Optional[RowBuilder.EvalCtx] = None
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) -> Expr:
88
- return self.components[2]
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 "R": the anchor is RELATIVE_PATH_ROOT
47
- return (
48
- f'{str(self._anchor) if self._anchor is not None else "R"}'
49
- f'{"." if isinstance(self.path_elements[0], str) else ""}{self._json_path()}'
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.owner is other.owner
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, data_row: DataRow, ctx: EvalCtx, profile: Optional[ExecProfile] = None, ignore_errors: bool = False
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()
pixeltable/func/tools.py CHANGED
@@ -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.FunctionCall':
54
- kwargs = {param.name: self.__extract_tool_arg(param, tool_calls) for param in self.parameters.values()}
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(tool_calls, func_name=func_name, param_name=param.name)
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(tool_calls, func_name=func_name, param_name=param.name)
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(tool_calls, func_name=func_name, param_name=param.name)
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(tool_calls, func_name=func_name, param_name=param.name)
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(tool_calls: dict[str, Any], func_name: str, param_name: str) -> Optional[str]:
117
- return _extract_arg(str, tool_calls, func_name, param_name)
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(tool_calls: dict[str, Any], func_name: str, param_name: str) -> Optional[int]:
122
- return _extract_arg(int, tool_calls, func_name, param_name)
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(tool_calls: dict[str, Any], func_name: str, param_name: str) -> Optional[float]:
127
- return _extract_arg(float, tool_calls, func_name, param_name)
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(tool_calls: dict[str, Any], func_name: str, param_name: str) -> Optional[bool]:
132
- return _extract_arg(bool, tool_calls, func_name, param_name)
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
- eval_fn: Callable[[Any], T], tool_calls: dict[str, Any], func_name: str, param_name: str
140
- ) -> Optional[T]:
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) > 0:
217
- return {tool_call['name']: {'args': tool_call['input']} for tool_call in anthropic_tool_calls}
218
- return None
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
- return {
820
- tool_call['function']['name']: {'args': json.loads(tool_call['function']['arguments'])}
821
- for tool_call in openai_tool_calls
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')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pixeltable
3
- Version: 0.3.5
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,5 +1,5 @@
1
1
  pixeltable/__init__.py,sha256=DRQQhIkaIs5-m6WzxRd4y0lO1pV4YQ9VHOPq7atc-lY,1638
2
- pixeltable/__version__.py,sha256=xz1unpHKoihfez0C3obp6Y_GaGHMbk1K0uZMleLspeU,112
2
+ pixeltable/__version__.py,sha256=6oQrE1_Rz1IIbTQsmlauBquucdig4kURpx8yfXgqpaQ,112
3
3
  pixeltable/catalog/__init__.py,sha256=bACh33HpWQed86eV8t9of_ClSXqZx5blZi4y8vJ7-EA,517
4
4
  pixeltable/catalog/catalog.py,sha256=JviNA1bRT_NzenR1mF5X23BYAS_1F3cdXSZeRfiEWus,8547
5
5
  pixeltable/catalog/column.py,sha256=lrCTuo22BnALGYeN5isNXBdTPATYNLFDQnrbtYMWpNE,9678
@@ -10,11 +10,11 @@ pixeltable/catalog/named_function.py,sha256=RHvKfzR5dyf5ixhmjr0swM2wqnYUhCIQuB6S
10
10
  pixeltable/catalog/path.py,sha256=5726gocGuq_QRQEhpLO-5y65Ebf1Sx-N2m4Hl6K1Vb4,1679
11
11
  pixeltable/catalog/path_dict.py,sha256=gu987TjUDrJibOhjr3-A7Kw9s_ZDAB4tornGKRCgwJo,6493
12
12
  pixeltable/catalog/schema_object.py,sha256=2xeV9XfriawLWT5B8-fdRJ5HxrnMkhsXS3XEAcALHe4,2383
13
- pixeltable/catalog/table.py,sha256=Gl_ULJiVeaNyNQer-Dm1Wrk0wVnvWh4TD3EqxbyfN74,62421
13
+ pixeltable/catalog/table.py,sha256=ZtXYWDfoQ6e2lkw45FRAGFQFqJuVrDFMz6IlnLX3j58,62513
14
14
  pixeltable/catalog/table_version.py,sha256=NAT6x1_Z3DbNo3cpd_wK4g6kNC6en-ISLsEYzp8dtOc,60696
15
15
  pixeltable/catalog/table_version_path.py,sha256=yU2bIQlSq0wMzM6J_CvPWBvgLfNUdObsm-jlIahDxzM,5897
16
16
  pixeltable/catalog/view.py,sha256=5B3RpXGwM-dJWL5g4ClInBow6QVJw4T3gSvFR8b82Bo,13037
17
- pixeltable/dataframe.py,sha256=heURzMRiTGxpVxoXoE8gsnD-f-X27Q8aYPn_AwBOwGM,49426
17
+ pixeltable/dataframe.py,sha256=oRJm6cQEOQIhiOQKLBX4KuPNwq3PlH5V0UrQf8iz_hE,49422
18
18
  pixeltable/env.py,sha256=plMNx4bhYboDM6otx1qWfDH2g1lmBBShPmHOUI-44Bk,36367
19
19
  pixeltable/exceptions.py,sha256=NuFY2WtkQpLfLHT_J70kOw9Tr0kEDkkgo-u7As4Gaq4,410
20
20
  pixeltable/exec/__init__.py,sha256=Qi0s2BEM8O8MPdYGQAIzclv2GNFsoCPJFvA6s5Tjc_o,489
@@ -40,7 +40,7 @@ pixeltable/exprs/column_property_ref.py,sha256=dkScOhj5rUUB_s26iWhrTz_YZQhYybfbP
40
40
  pixeltable/exprs/column_ref.py,sha256=MBWrNwnbRe0Hswu0q_Arerm9JoQs_0pNSsCYVxXONx0,10891
41
41
  pixeltable/exprs/comparison.py,sha256=TABLNY3tIf-eJWBmFTD00PsLrd_aQTYRJFykf1BXihU,5200
42
42
  pixeltable/exprs/compound_predicate.py,sha256=ZN_JL97OZfTwdfgXF2t57EGyTYrpsBHaduZWRuBAekk,3832
43
- pixeltable/exprs/data_row.py,sha256=eW9NG31cTZUjlJfBLyOB-MuiTEfXXrfVmeeKqIjy31k,10716
43
+ pixeltable/exprs/data_row.py,sha256=kpjVj5VlJC6S_e6xaY9xVAquD34VUMg3zEyBqun4teQ,10823
44
44
  pixeltable/exprs/expr.py,sha256=3hpD-_4PMoGPOSkACZXnV_ZI6HQmdoMcJm_25Iy82sI,32474
45
45
  pixeltable/exprs/expr_dict.py,sha256=wf82K-aCPHZcM2A-VbE_0p5OzQFfVsI65uzMLp4Uwu4,1589
46
46
  pixeltable/exprs/expr_set.py,sha256=kkcG9df8fQOblNIKz2xciw9qfu2CnTWb4qwJKYVTUx8,2578
@@ -49,12 +49,12 @@ pixeltable/exprs/globals.py,sha256=y5bhU21ME57dTuz9iSU1jA56nWhDe_t-OHFYthwngM8,2
49
49
  pixeltable/exprs/in_predicate.py,sha256=nNmo7slUvZCR2GN9amWCA8eQv83NdTjXTphjqawpLDw,3799
50
50
  pixeltable/exprs/inline_expr.py,sha256=dLivsKlh_xEfXXXd5tSogg0cAwMOWTv8Hh2DBgKOdzs,7985
51
51
  pixeltable/exprs/is_null.py,sha256=rnusy1j33o48Z-qjguj09G7AmsBHFJI5SWQXOAjgKQw,1092
52
- pixeltable/exprs/json_mapper.py,sha256=gQj_MxDonYrh3yCT4Dvmy1QBpKCJMn5Qzky8RRUAiwA,4547
53
- pixeltable/exprs/json_path.py,sha256=XEuth-i24slqAYvnAkb8BfkmrvGACK8afiEyaA27oDU,6745
52
+ pixeltable/exprs/json_mapper.py,sha256=Tir-ZeSANfi8D9T469PALWzICoslc_80xrbcpTZfka4,5156
53
+ pixeltable/exprs/json_path.py,sha256=wCYvaaMG9C3PXXveJIhdMU6ml4H547UrQWJUr6CCSaY,6854
54
54
  pixeltable/exprs/literal.py,sha256=kvuQTl1N5hMFrJNgDtVkTBkEDqtSsOcTGLjndh7CbwM,4315
55
55
  pixeltable/exprs/method_ref.py,sha256=CfZWjzjQ9tDVEOkSRm32MSUqVZHLq8qvMGLpORQpoDo,2616
56
- pixeltable/exprs/object_ref.py,sha256=OS4Om2BCG3PQEFK5VZ2APTPn_b0D22d9g30GM5XpfYs,1283
57
- pixeltable/exprs/row_builder.py,sha256=lDl2xg82vORu7n-VMU210cpRGvSCO5o4spsfC5gK6Qs,20040
56
+ pixeltable/exprs/object_ref.py,sha256=DS7iD3jqN5ZVuLIf6jjtuOTtTtlcHwxRmUG9LfZLsE4,1983
57
+ pixeltable/exprs/row_builder.py,sha256=KnPGk-nq3CZcMs97KDvcsTW7R7SElFp-TxdKTLhty8I,20336
58
58
  pixeltable/exprs/rowid_ref.py,sha256=cOimh6mLhJsIngUC48yawEGoaevVYvi1QUbbksfysaU,4468
59
59
  pixeltable/exprs/similarity_expr.py,sha256=MHp71EEcyaAFeoWtQQhsxjPWD7b6iZCFkOe_EwFfp_U,4378
60
60
  pixeltable/exprs/sql_element_cache.py,sha256=NPOqhjcvwNi_jIYpOOODQ96PI-KRMVBWVnhhLNHxHl4,1364
@@ -73,10 +73,10 @@ pixeltable/func/function_registry.py,sha256=21E6KVjxuR_EPelVeun7Igk0YWH2zXjDwItg
73
73
  pixeltable/func/globals.py,sha256=5Wo4GPxYgHRRk5nvV0h_lAthKSalxKvj5n1p-uMPR0U,1501
74
74
  pixeltable/func/query_template_function.py,sha256=p3_NaDBrlMqT2HT8QM-9fzqgko0n6W3CY-z63grqenk,5277
75
75
  pixeltable/func/signature.py,sha256=Mv-dt2Z87y_hx2jFJiA9mVs3M8of3EJcVqo63YUoi9Y,13501
76
- pixeltable/func/tools.py,sha256=gwAzqWPuLSUBxWJ4IMYVWDsoVTUDxZm-Dh3RRed-ro0,5860
76
+ pixeltable/func/tools.py,sha256=tibSQfl61rKzBe3BNsq2RK5fUSyXDwCMjCCaQvopX1U,5727
77
77
  pixeltable/func/udf.py,sha256=qpXkf3-ZO9w6EHj9heniGEWC2lF3AgZEWD2-PaAjDf4,13139
78
78
  pixeltable/functions/__init__.py,sha256=QkuN-klq0s-D4PDrqYWNvPzPflmBRLe6Hh-RzeQVrz0,517
79
- pixeltable/functions/anthropic.py,sha256=s3tkpbSG0IUWPWI3pMWwvs_8FchFZdvr0gMZ35G6aBU,9079
79
+ pixeltable/functions/anthropic.py,sha256=HPj9keD4XAjs1dqw6XOP8-onv7BkyNWFd4pPW5kD1EY,9303
80
80
  pixeltable/functions/audio.py,sha256=7213nTnqKJ6vM9kalaoJ283OwX5SGEJN10vDhaRNZ6E,644
81
81
  pixeltable/functions/deepseek.py,sha256=gmGknLIrsnrsALXcHCr6Y2AltR68juRVROkcbeS6WVQ,3814
82
82
  pixeltable/functions/fireworks.py,sha256=v9F-l3E73QhcyIsz720jJbtZV_GcyMu83zOV3ZC2Pd8,5024
@@ -89,7 +89,7 @@ pixeltable/functions/llama_cpp.py,sha256=1nVXgU5ymuNblVNqRQv3iAEvlYpqzDZPAjYnAOH
89
89
  pixeltable/functions/math.py,sha256=WPoH9zD9_GdwvBs-FSC3Sqb70gOPNouhPcBZABsuLwI,1541
90
90
  pixeltable/functions/mistralai.py,sha256=H2onsnW1R_SaFN5SI_JWO0A5lJdlsnKxmtIu2m19cEg,6212
91
91
  pixeltable/functions/ollama.py,sha256=Et0l7XEMaNLxDwy3qTblljomjCkOQroY1Z7a-Ajmshk,4218
92
- pixeltable/functions/openai.py,sha256=KvNrj0IF8-2M0hPDQtwDhrqmVsQxvXlnqOQ0nPSbxG8,29871
92
+ pixeltable/functions/openai.py,sha256=rT2urBavT44e2LVH6TPIpScPIu7SvceCykN0F_AaqlU,30072
93
93
  pixeltable/functions/replicate.py,sha256=BQ5iaFJnw5MioL3X08DQiH41xQ_Pi2H5DDEasux9-fE,2454
94
94
  pixeltable/functions/string.py,sha256=1vFlbqKVm2n6jdh23BIA_8MBJJiNyxbQoFs5tJPgpy4,20433
95
95
  pixeltable/functions/timestamp.py,sha256=KKOw7l1hErYp8QQfFiWVTf7QowZszOyHJu-OJDKaXSg,9114
@@ -165,8 +165,8 @@ pixeltable/utils/pytorch.py,sha256=8lJT1SyP9jTMN7uLtrj9T_rGPEYRID44rWXbjBhRUrU,3
165
165
  pixeltable/utils/s3.py,sha256=pxip2MlCqd2Qon2dzJXzfxvwtZyc-BAsjAnLL4J_OXY,587
166
166
  pixeltable/utils/sql.py,sha256=JX_fNI_SJWVUcXif5ho5qVhfJKFupOCFLLrHCMcbzLk,796
167
167
  pixeltable/utils/transactional_directory.py,sha256=4Q8UTylEyw-aZa-NVjfjGR9_JHRJTGQH1k1LNFaZukY,1349
168
- pixeltable-0.3.5.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
169
- pixeltable-0.3.5.dist-info/METADATA,sha256=nC5GuOA9uMFi7ciAGMO1Ev0dA3mSdl5x4d2G4OSUtlo,18899
170
- pixeltable-0.3.5.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
171
- pixeltable-0.3.5.dist-info/entry_points.txt,sha256=ToOd-pRgG7AitEBgYoBCRRB4-KVDQ0pj_9T4a1LgwA4,97
172
- pixeltable-0.3.5.dist-info/RECORD,,
168
+ pixeltable-0.3.6.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
169
+ pixeltable-0.3.6.dist-info/METADATA,sha256=3SdDqzWH3T3JSTtAkjumM6HQEUimrhB-RbBWdQmi0Og,18899
170
+ pixeltable-0.3.6.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
171
+ pixeltable-0.3.6.dist-info/entry_points.txt,sha256=ToOd-pRgG7AitEBgYoBCRRB4-KVDQ0pj_9T4a1LgwA4,97
172
+ pixeltable-0.3.6.dist-info/RECORD,,