cocoindex 0.2.10__cp311-abi3-macosx_10_12_x86_64.whl → 0.2.11__cp311-abi3-macosx_10_12_x86_64.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.
- cocoindex/__init__.py +5 -0
- cocoindex/_engine.abi3.so +0 -0
- cocoindex/auth_registry.py +2 -13
- cocoindex/convert.py +2 -0
- cocoindex/flow.py +79 -18
- cocoindex/op.py +5 -11
- cocoindex/query_handler.py +51 -0
- cocoindex/runtime.py +8 -1
- {cocoindex-0.2.10.dist-info → cocoindex-0.2.11.dist-info}/METADATA +1 -1
- {cocoindex-0.2.10.dist-info → cocoindex-0.2.11.dist-info}/RECORD +13 -12
- {cocoindex-0.2.10.dist-info → cocoindex-0.2.11.dist-info}/licenses/THIRD_PARTY_NOTICES.html +1 -1
- {cocoindex-0.2.10.dist-info → cocoindex-0.2.11.dist-info}/WHEEL +0 -0
- {cocoindex-0.2.10.dist-info → cocoindex-0.2.11.dist-info}/entry_points.txt +0 -0
cocoindex/__init__.py
CHANGED
@@ -24,6 +24,7 @@ from .llm import LlmSpec, LlmApiType
|
|
24
24
|
from .index import VectorSimilarityMetric, VectorIndexDef, IndexOptions
|
25
25
|
from .setting import DatabaseConnectionSpec, Settings, ServerSettings
|
26
26
|
from .setting import get_app_namespace
|
27
|
+
from .query_handler import QueryHandlerResultFields, QueryInfo, QueryOutput
|
27
28
|
from .typing import (
|
28
29
|
Int64,
|
29
30
|
Float32,
|
@@ -95,4 +96,8 @@ __all__ = [
|
|
95
96
|
"Range",
|
96
97
|
"Vector",
|
97
98
|
"Json",
|
99
|
+
# Query handler
|
100
|
+
"QueryHandlerResultFields",
|
101
|
+
"QueryInfo",
|
102
|
+
"QueryOutput",
|
98
103
|
]
|
cocoindex/_engine.abi3.so
CHANGED
Binary file
|
cocoindex/auth_registry.py
CHANGED
@@ -11,18 +11,6 @@ from .convert import dump_engine_object
|
|
11
11
|
|
12
12
|
T = TypeVar("T")
|
13
13
|
|
14
|
-
# Global atomic counter for generating unique auth entry keys
|
15
|
-
_counter_lock = threading.Lock()
|
16
|
-
_auth_key_counter = 0
|
17
|
-
|
18
|
-
|
19
|
-
def _generate_auth_key() -> str:
|
20
|
-
"""Generate a unique auth entry key using a global atomic counter."""
|
21
|
-
global _auth_key_counter # pylint: disable=global-statement
|
22
|
-
with _counter_lock:
|
23
|
-
_auth_key_counter += 1
|
24
|
-
return f"__auth_{_auth_key_counter}"
|
25
|
-
|
26
14
|
|
27
15
|
@dataclass
|
28
16
|
class TransientAuthEntryReference(Generic[T]):
|
@@ -37,7 +25,8 @@ class AuthEntryReference(TransientAuthEntryReference[T]):
|
|
37
25
|
|
38
26
|
def add_transient_auth_entry(value: T) -> TransientAuthEntryReference[T]:
|
39
27
|
"""Add an auth entry to the registry. Returns its reference."""
|
40
|
-
|
28
|
+
key = _engine.add_transient_auth_entry(dump_engine_object(value))
|
29
|
+
return TransientAuthEntryReference(key)
|
41
30
|
|
42
31
|
|
43
32
|
def add_auth_entry(key: str, value: T) -> AuthEntryReference[T]:
|
cocoindex/convert.py
CHANGED
@@ -616,6 +616,8 @@ def dump_engine_object(v: Any) -> Any:
|
|
616
616
|
return s
|
617
617
|
elif isinstance(v, (list, tuple)):
|
618
618
|
return [dump_engine_object(item) for item in v]
|
619
|
+
elif isinstance(v, np.ndarray):
|
620
|
+
return v.tolist()
|
619
621
|
elif isinstance(v, dict):
|
620
622
|
return {k: dump_engine_object(v) for k, v in v.items()}
|
621
623
|
return v
|
cocoindex/flow.py
CHANGED
@@ -38,9 +38,10 @@ from .convert import (
|
|
38
38
|
make_engine_value_encoder,
|
39
39
|
)
|
40
40
|
from .op import FunctionSpec
|
41
|
-
from .runtime import execution_context
|
41
|
+
from .runtime import execution_context, to_async_call
|
42
42
|
from .setup import SetupChangeBundle
|
43
43
|
from .typing import analyze_type_info, encode_enriched_type
|
44
|
+
from .query_handler import QueryHandlerInfo, QueryHandlerResultFields
|
44
45
|
from .validation import (
|
45
46
|
validate_flow_name,
|
46
47
|
validate_full_flow_name,
|
@@ -694,23 +695,18 @@ class Flow:
|
|
694
695
|
"""
|
695
696
|
|
696
697
|
_name: str
|
697
|
-
|
698
|
+
_engine_flow_creator: Callable[[], _engine.Flow]
|
699
|
+
|
700
|
+
_lazy_flow_lock: Lock
|
701
|
+
_lazy_query_handler_args: list[tuple[Any, ...]]
|
702
|
+
_lazy_engine_flow: _engine.Flow | None = None
|
698
703
|
|
699
704
|
def __init__(self, name: str, engine_flow_creator: Callable[[], _engine.Flow]):
|
700
705
|
validate_flow_name(name)
|
701
706
|
self._name = name
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
def _lazy_engine_flow() -> _engine.Flow:
|
706
|
-
nonlocal engine_flow, lock
|
707
|
-
if engine_flow is None:
|
708
|
-
with lock:
|
709
|
-
if engine_flow is None:
|
710
|
-
engine_flow = engine_flow_creator()
|
711
|
-
return engine_flow
|
712
|
-
|
713
|
-
self._lazy_engine_flow = _lazy_engine_flow
|
707
|
+
self._engine_flow_creator = engine_flow_creator
|
708
|
+
self._lazy_flow_lock = Lock()
|
709
|
+
self._lazy_query_handler_args = []
|
714
710
|
|
715
711
|
def _render_spec(self, verbose: bool = False) -> Tree:
|
716
712
|
"""
|
@@ -794,15 +790,33 @@ class Flow:
|
|
794
790
|
"""
|
795
791
|
Get the engine flow.
|
796
792
|
"""
|
797
|
-
if self._lazy_engine_flow is None:
|
798
|
-
|
799
|
-
return self.
|
793
|
+
if self._lazy_engine_flow is not None:
|
794
|
+
return self._lazy_engine_flow
|
795
|
+
return self._internal_flow()
|
800
796
|
|
801
797
|
async def internal_flow_async(self) -> _engine.Flow:
|
802
798
|
"""
|
803
799
|
Get the engine flow. The async version.
|
804
800
|
"""
|
805
|
-
|
801
|
+
if self._lazy_engine_flow is not None:
|
802
|
+
return self._lazy_engine_flow
|
803
|
+
return await asyncio.to_thread(self._internal_flow)
|
804
|
+
|
805
|
+
def _internal_flow(self) -> _engine.Flow:
|
806
|
+
"""
|
807
|
+
Get the engine flow. The async version.
|
808
|
+
"""
|
809
|
+
with self._lazy_flow_lock:
|
810
|
+
if self._lazy_engine_flow is not None:
|
811
|
+
return self._lazy_engine_flow
|
812
|
+
|
813
|
+
engine_flow = self._engine_flow_creator()
|
814
|
+
self._lazy_engine_flow = engine_flow
|
815
|
+
for args in self._lazy_query_handler_args:
|
816
|
+
engine_flow.add_query_handler(*args)
|
817
|
+
self._lazy_query_handler_args = []
|
818
|
+
|
819
|
+
return engine_flow
|
806
820
|
|
807
821
|
def setup(self, report_to_stdout: bool = False) -> None:
|
808
822
|
"""
|
@@ -847,6 +861,53 @@ class Flow:
|
|
847
861
|
with _flows_lock:
|
848
862
|
del _flows[self.name]
|
849
863
|
|
864
|
+
def add_query_handler(
|
865
|
+
self,
|
866
|
+
name: str,
|
867
|
+
handler: Callable[[str], Any],
|
868
|
+
/,
|
869
|
+
*,
|
870
|
+
result_fields: QueryHandlerResultFields | None = None,
|
871
|
+
) -> None:
|
872
|
+
"""
|
873
|
+
Add a query handler to the flow.
|
874
|
+
"""
|
875
|
+
async_handler = to_async_call(handler)
|
876
|
+
|
877
|
+
async def _handler(query: str) -> dict[str, Any]:
|
878
|
+
handler_result = await async_handler(query)
|
879
|
+
return {
|
880
|
+
"results": [
|
881
|
+
[(k, dump_engine_object(v)) for (k, v) in result.items()]
|
882
|
+
for result in handler_result.results
|
883
|
+
],
|
884
|
+
"query_info": dump_engine_object(handler_result.query_info),
|
885
|
+
}
|
886
|
+
|
887
|
+
handler_info = dump_engine_object(QueryHandlerInfo(result_fields=result_fields))
|
888
|
+
with self._lazy_flow_lock:
|
889
|
+
if self._lazy_engine_flow is not None:
|
890
|
+
self._lazy_engine_flow.add_query_handler(name, _handler, handler_info)
|
891
|
+
else:
|
892
|
+
self._lazy_query_handler_args.append((name, _handler, handler_info))
|
893
|
+
|
894
|
+
def query_handler(
|
895
|
+
self,
|
896
|
+
name: str | None = None,
|
897
|
+
result_fields: QueryHandlerResultFields | None = None,
|
898
|
+
) -> Callable[[Callable[[str], Any]], Callable[[str], Any]]:
|
899
|
+
"""
|
900
|
+
A decorator to declare a query handler.
|
901
|
+
"""
|
902
|
+
|
903
|
+
def _inner(handler: Callable[[str], Any]) -> Callable[[str], Any]:
|
904
|
+
self.add_query_handler(
|
905
|
+
name or handler.__qualname__, handler, result_fields=result_fields
|
906
|
+
)
|
907
|
+
return handler
|
908
|
+
|
909
|
+
return _inner
|
910
|
+
|
850
911
|
|
851
912
|
def _create_lazy_flow(
|
852
913
|
name: str | None, fl_def: Callable[[FlowBuilder, DataScope], None]
|
cocoindex/op.py
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
Facilities for defining cocoindex operations.
|
3
3
|
"""
|
4
4
|
|
5
|
-
import asyncio
|
6
5
|
import dataclasses
|
7
6
|
import inspect
|
8
7
|
from enum import Enum
|
@@ -32,6 +31,7 @@ from .typing import (
|
|
32
31
|
AnalyzedAnyType,
|
33
32
|
AnalyzedDictType,
|
34
33
|
)
|
34
|
+
from .runtime import to_async_call
|
35
35
|
|
36
36
|
|
37
37
|
class OpCategory(Enum):
|
@@ -150,12 +150,6 @@ class OpArgs:
|
|
150
150
|
arg_relationship: tuple[ArgRelationship, str] | None = None
|
151
151
|
|
152
152
|
|
153
|
-
def _to_async_call(call: Callable[..., Any]) -> Callable[..., Awaitable[Any]]:
|
154
|
-
if inspect.iscoroutinefunction(call):
|
155
|
-
return call
|
156
|
-
return lambda *args, **kwargs: asyncio.to_thread(lambda: call(*args, **kwargs))
|
157
|
-
|
158
|
-
|
159
153
|
@dataclasses.dataclass
|
160
154
|
class _ArgInfo:
|
161
155
|
decoder: Callable[[Any], Any]
|
@@ -319,8 +313,8 @@ def _register_op_factory(
|
|
319
313
|
"""
|
320
314
|
prepare_method = getattr(self._executor, "prepare", None)
|
321
315
|
if prepare_method is not None:
|
322
|
-
await
|
323
|
-
self._acall =
|
316
|
+
await to_async_call(prepare_method)()
|
317
|
+
self._acall = to_async_call(self._executor.__call__)
|
324
318
|
|
325
319
|
async def __call__(self, *args: Any, **kwargs: Any) -> Any:
|
326
320
|
decoded_args = []
|
@@ -461,12 +455,12 @@ class _TargetConnector:
|
|
461
455
|
self._get_persistent_key_fn = _get_required_method(
|
462
456
|
connector_cls, "get_persistent_key"
|
463
457
|
)
|
464
|
-
self._apply_setup_change_async_fn =
|
458
|
+
self._apply_setup_change_async_fn = to_async_call(
|
465
459
|
_get_required_method(connector_cls, "apply_setup_change")
|
466
460
|
)
|
467
461
|
|
468
462
|
mutate_fn = _get_required_method(connector_cls, "mutate")
|
469
|
-
self._mutate_async_fn =
|
463
|
+
self._mutate_async_fn = to_async_call(mutate_fn)
|
470
464
|
|
471
465
|
# Store the type annotation for later use
|
472
466
|
self._mutatation_type = self._analyze_mutate_mutation_type(
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import dataclasses
|
2
|
+
import numpy as np
|
3
|
+
from numpy import typing as npt
|
4
|
+
from typing import Generic, TypeVar
|
5
|
+
from .index import VectorSimilarityMetric
|
6
|
+
|
7
|
+
|
8
|
+
@dataclasses.dataclass
|
9
|
+
class QueryHandlerResultFields:
|
10
|
+
"""
|
11
|
+
Specify field names in query results returned by the query handler.
|
12
|
+
This provides metadata for tools like CocoInsight to recognize structure of the query results.
|
13
|
+
"""
|
14
|
+
|
15
|
+
embedding: list[str] = dataclasses.field(default_factory=list)
|
16
|
+
score: str | None = None
|
17
|
+
|
18
|
+
|
19
|
+
@dataclasses.dataclass
|
20
|
+
class QueryHandlerInfo:
|
21
|
+
"""
|
22
|
+
Info to configure a query handler.
|
23
|
+
"""
|
24
|
+
|
25
|
+
result_fields: QueryHandlerResultFields | None = None
|
26
|
+
|
27
|
+
|
28
|
+
@dataclasses.dataclass
|
29
|
+
class QueryInfo:
|
30
|
+
"""
|
31
|
+
Info about the query.
|
32
|
+
"""
|
33
|
+
|
34
|
+
embedding: list[float] | npt.NDArray[np.float32] | None = None
|
35
|
+
similarity_metric: VectorSimilarityMetric | None = None
|
36
|
+
|
37
|
+
|
38
|
+
R = TypeVar("R")
|
39
|
+
|
40
|
+
|
41
|
+
@dataclasses.dataclass
|
42
|
+
class QueryOutput(Generic[R]):
|
43
|
+
"""
|
44
|
+
Output of a query handler.
|
45
|
+
|
46
|
+
results: list of results. Each result can be a dict or a dataclass.
|
47
|
+
query_info: Info about the query.
|
48
|
+
"""
|
49
|
+
|
50
|
+
results: list[R]
|
51
|
+
query_info: QueryInfo = dataclasses.field(default_factory=QueryInfo)
|
cocoindex/runtime.py
CHANGED
@@ -5,7 +5,8 @@ manner.
|
|
5
5
|
|
6
6
|
import threading
|
7
7
|
import asyncio
|
8
|
-
|
8
|
+
import inspect
|
9
|
+
from typing import Any, Callable, Coroutine, TypeVar, Awaitable
|
9
10
|
|
10
11
|
|
11
12
|
T = TypeVar("T")
|
@@ -35,3 +36,9 @@ class _ExecutionContext:
|
|
35
36
|
|
36
37
|
|
37
38
|
execution_context = _ExecutionContext()
|
39
|
+
|
40
|
+
|
41
|
+
def to_async_call(call: Callable[..., Any]) -> Callable[..., Awaitable[Any]]:
|
42
|
+
if inspect.iscoroutinefunction(call):
|
43
|
+
return call
|
44
|
+
return lambda *args, **kwargs: asyncio.to_thread(lambda: call(*args, **kwargs))
|
@@ -1,20 +1,21 @@
|
|
1
|
-
cocoindex-0.2.
|
2
|
-
cocoindex-0.2.
|
3
|
-
cocoindex-0.2.
|
4
|
-
cocoindex-0.2.
|
5
|
-
cocoindex/__init__.py,sha256=
|
6
|
-
cocoindex/_engine.abi3.so,sha256=
|
7
|
-
cocoindex/auth_registry.py,sha256=
|
1
|
+
cocoindex-0.2.11.dist-info/METADATA,sha256=u-dE4rSfVStoZHzhM01B2D0N-8AqLGiV3NAYs1zs19U,12999
|
2
|
+
cocoindex-0.2.11.dist-info/WHEEL,sha256=N8W3-0eDM6igWj-H12r7VkxoMaJIqJLxUyWCFstEaGg,105
|
3
|
+
cocoindex-0.2.11.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
|
4
|
+
cocoindex-0.2.11.dist-info/licenses/THIRD_PARTY_NOTICES.html,sha256=o8g8gIN-zaK02_7ZMPlqompannwA2SwEB0e30CKRN1E,717804
|
5
|
+
cocoindex/__init__.py,sha256=AsoNLBgjJ-1AEKtwTnENJM9dEilHTq6rJ4qWUzGKSdc,2428
|
6
|
+
cocoindex/_engine.abi3.so,sha256=H-x9Yqz5RWpB0vkeGPpjb3QuOX1h8-ocQlqrPaXCnqw,70039588
|
7
|
+
cocoindex/auth_registry.py,sha256=9GgeuyE48vYhsJQJgI-uRjUviZkrQE63MUenP3OREko,1145
|
8
8
|
cocoindex/cli.py,sha256=69X30bFTFdM7c0_6lgIHR19CeQ7UEkobEQYihy8IdOQ,21599
|
9
|
-
cocoindex/convert.py,sha256=
|
10
|
-
cocoindex/flow.py,sha256=
|
9
|
+
cocoindex/convert.py,sha256=Apk5PU4XGnSvEE2HMRN2W9H4ApBIHnkupegv_-TaVfA,22152
|
10
|
+
cocoindex/flow.py,sha256=u_ta8wW5oGTDINs2dY4d_1hybySp3wuX79VJ4BDXZDc,39767
|
11
11
|
cocoindex/functions.py,sha256=09erNt3WbzY9l1KER-akBF2O5-6xEahV2ORBECaL6yk,12260
|
12
12
|
cocoindex/index.py,sha256=j93B9jEvvLXHtpzKWL88SY6wCGEoPgpsQhEGHlyYGFg,540
|
13
13
|
cocoindex/lib.py,sha256=0XheDF7fiFdqExpdqzU-VKun_Zll6DwZ5JfTm7u42aY,2284
|
14
14
|
cocoindex/llm.py,sha256=Pv_cdnRngTLtuLU9AUmS8izIHhcKVnuBNolC33f9BDI,851
|
15
|
-
cocoindex/op.py,sha256=
|
15
|
+
cocoindex/op.py,sha256=SRtI5ApgRQJHNsljd9Z2qNdS68_pYYQj9oVg3Bqc8W4,21416
|
16
16
|
cocoindex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
|
-
cocoindex/
|
17
|
+
cocoindex/query_handler.py,sha256=o9XFnpXWa00pAFImJ9oq-_kjI7w69dgCalkq63H9mA8,1192
|
18
|
+
cocoindex/runtime.py,sha256=4NxcltaDZvA3RR3Pnt6gH_f99jcWSyMH_1Xi5BjbtwY,1342
|
18
19
|
cocoindex/setting.py,sha256=1Dx8ktjwf-8BiXrbsmfn5Mzudb2SQYqFdRnSNGVKaLk,4960
|
19
20
|
cocoindex/setup.py,sha256=7uIHKN4FOCuoidPXcKyGTrkqpkl9luL49-6UcnMxYzw,3068
|
20
21
|
cocoindex/sources.py,sha256=FYz7cWYasLGDaYoIEQ1dF2uprgUETHWsTIrIS7n6pQE,3188
|
@@ -30,4 +31,4 @@ cocoindex/typing.py,sha256=lEQYIzAGVKQp6RnhyeopY9Q7xEED7yQj3ZMxvTPblV8,14200
|
|
30
31
|
cocoindex/user_app_loader.py,sha256=bc3Af-gYRxJ9GpObtpjegZY855oQBCv5FGkrkWV2yGY,1873
|
31
32
|
cocoindex/utils.py,sha256=hUhX-XV6XGCtJSEIpBOuDv6VvqImwPlgBxztBTw7u0U,598
|
32
33
|
cocoindex/validation.py,sha256=PZnJoby4sLbsmPv9fOjOQXuefjfZ7gmtsiTGU8SH-tc,3090
|
33
|
-
cocoindex-0.2.
|
34
|
+
cocoindex-0.2.11.dist-info/RECORD,,
|
@@ -2428,7 +2428,7 @@ Software.
|
|
2428
2428
|
<h3 id="Apache-2.0">Apache License 2.0</h3>
|
2429
2429
|
<h4>Used by:</h4>
|
2430
2430
|
<ul class="license-used-by">
|
2431
|
-
<li><a href=" https://crates.io/crates/cocoindex ">cocoindex 0.2.
|
2431
|
+
<li><a href=" https://crates.io/crates/cocoindex ">cocoindex 0.2.11</a></li>
|
2432
2432
|
<li><a href=" https://github.com/awesomized/crc-fast-rust ">crc-fast 1.3.0</a></li>
|
2433
2433
|
<li><a href=" https://github.com/qdrant/rust-client ">qdrant-client 1.15.0</a></li>
|
2434
2434
|
</ul>
|
File without changes
|
File without changes
|