cocoindex 0.2.11__cp311-abi3-manylinux_2_28_aarch64.whl → 0.2.13__cp311-abi3-manylinux_2_28_aarch64.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/_engine.abi3.so +0 -0
- cocoindex/auth_registry.py +6 -2
- cocoindex/convert.py +183 -27
- cocoindex/flow.py +4 -2
- cocoindex/op.py +163 -41
- cocoindex/query_handler.py +8 -2
- cocoindex/targets/__init__.py +5 -0
- cocoindex/{targets.py → targets/_engine_builtin_specs.py} +4 -4
- cocoindex/targets/lancedb.py +460 -0
- cocoindex/tests/test_convert.py +51 -26
- cocoindex/tests/test_load_convert.py +118 -0
- cocoindex/tests/test_typing.py +126 -2
- cocoindex/typing.py +207 -0
- {cocoindex-0.2.11.dist-info → cocoindex-0.2.13.dist-info}/METADATA +6 -1
- {cocoindex-0.2.11.dist-info → cocoindex-0.2.13.dist-info}/RECORD +18 -15
- {cocoindex-0.2.11.dist-info → cocoindex-0.2.13.dist-info}/licenses/THIRD_PARTY_NOTICES.html +27 -33
- {cocoindex-0.2.11.dist-info → cocoindex-0.2.13.dist-info}/WHEEL +0 -0
- {cocoindex-0.2.11.dist-info → cocoindex-0.2.13.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,118 @@
|
|
1
|
+
import dataclasses
|
2
|
+
import datetime
|
3
|
+
from typing import TypedDict, NamedTuple
|
4
|
+
|
5
|
+
import numpy as np
|
6
|
+
from numpy.typing import NDArray
|
7
|
+
|
8
|
+
from cocoindex.convert import dump_engine_object, load_engine_object
|
9
|
+
|
10
|
+
|
11
|
+
@dataclasses.dataclass
|
12
|
+
class LocalTargetFieldMapping:
|
13
|
+
source: str
|
14
|
+
target: str | None = None
|
15
|
+
|
16
|
+
|
17
|
+
@dataclasses.dataclass
|
18
|
+
class LocalNodeFromFields:
|
19
|
+
label: str
|
20
|
+
fields: list[LocalTargetFieldMapping]
|
21
|
+
|
22
|
+
|
23
|
+
@dataclasses.dataclass
|
24
|
+
class LocalNodes:
|
25
|
+
kind = "Node"
|
26
|
+
label: str
|
27
|
+
|
28
|
+
|
29
|
+
@dataclasses.dataclass
|
30
|
+
class LocalRelationships:
|
31
|
+
kind = "Relationship"
|
32
|
+
rel_type: str
|
33
|
+
source: LocalNodeFromFields
|
34
|
+
target: LocalNodeFromFields
|
35
|
+
|
36
|
+
|
37
|
+
class LocalPoint(NamedTuple):
|
38
|
+
x: int
|
39
|
+
y: int
|
40
|
+
|
41
|
+
|
42
|
+
class UserInfo(TypedDict):
|
43
|
+
id: str
|
44
|
+
age: int
|
45
|
+
|
46
|
+
|
47
|
+
def test_timedelta_roundtrip_via_dump_load() -> None:
|
48
|
+
td = datetime.timedelta(days=1, hours=2, minutes=3, seconds=4, microseconds=500)
|
49
|
+
dumped = dump_engine_object(td)
|
50
|
+
loaded = load_engine_object(datetime.timedelta, dumped)
|
51
|
+
assert isinstance(loaded, datetime.timedelta)
|
52
|
+
assert loaded == td
|
53
|
+
|
54
|
+
|
55
|
+
def test_ndarray_roundtrip_via_dump_load() -> None:
|
56
|
+
value: NDArray[np.float32] = np.array([1.0, 2.0, 3.0], dtype=np.float32)
|
57
|
+
dumped = dump_engine_object(value)
|
58
|
+
assert dumped == [1.0, 2.0, 3.0]
|
59
|
+
loaded = load_engine_object(NDArray[np.float32], dumped)
|
60
|
+
assert isinstance(loaded, np.ndarray)
|
61
|
+
assert loaded.dtype == np.float32
|
62
|
+
assert np.array_equal(loaded, value)
|
63
|
+
|
64
|
+
|
65
|
+
def test_nodes_kind_is_carried() -> None:
|
66
|
+
node = LocalNodes(label="User")
|
67
|
+
dumped = dump_engine_object(node)
|
68
|
+
# dumped should include discriminator
|
69
|
+
assert dumped.get("kind") == "Node"
|
70
|
+
# load back
|
71
|
+
loaded = load_engine_object(LocalNodes, dumped)
|
72
|
+
assert isinstance(loaded, LocalNodes)
|
73
|
+
# class-level attribute is preserved
|
74
|
+
assert getattr(loaded, "kind", None) == "Node"
|
75
|
+
assert loaded.label == "User"
|
76
|
+
|
77
|
+
|
78
|
+
def test_relationships_union_discriminator() -> None:
|
79
|
+
rel = LocalRelationships(
|
80
|
+
rel_type="LIKES",
|
81
|
+
source=LocalNodeFromFields(
|
82
|
+
label="User", fields=[LocalTargetFieldMapping("id")]
|
83
|
+
),
|
84
|
+
target=LocalNodeFromFields(
|
85
|
+
label="Item", fields=[LocalTargetFieldMapping("id")]
|
86
|
+
),
|
87
|
+
)
|
88
|
+
dumped = dump_engine_object(rel)
|
89
|
+
assert dumped.get("kind") == "Relationship"
|
90
|
+
loaded = load_engine_object(LocalNodes | LocalRelationships, dumped)
|
91
|
+
assert isinstance(loaded, LocalRelationships)
|
92
|
+
assert getattr(loaded, "kind", None) == "Relationship"
|
93
|
+
assert loaded.rel_type == "LIKES"
|
94
|
+
assert dataclasses.asdict(loaded.source) == {
|
95
|
+
"label": "User",
|
96
|
+
"fields": [{"source": "id", "target": None}],
|
97
|
+
}
|
98
|
+
assert dataclasses.asdict(loaded.target) == {
|
99
|
+
"label": "Item",
|
100
|
+
"fields": [{"source": "id", "target": None}],
|
101
|
+
}
|
102
|
+
|
103
|
+
|
104
|
+
def test_typed_dict_roundtrip_via_dump_load() -> None:
|
105
|
+
user: UserInfo = {"id": "u1", "age": 30}
|
106
|
+
dumped = dump_engine_object(user)
|
107
|
+
assert dumped == {"id": "u1", "age": 30}
|
108
|
+
loaded = load_engine_object(UserInfo, dumped)
|
109
|
+
assert loaded == user
|
110
|
+
|
111
|
+
|
112
|
+
def test_namedtuple_roundtrip_via_dump_load() -> None:
|
113
|
+
p = LocalPoint(1, 2)
|
114
|
+
dumped = dump_engine_object(p)
|
115
|
+
assert dumped == {"x": 1, "y": 2}
|
116
|
+
loaded = load_engine_object(LocalPoint, dumped)
|
117
|
+
assert isinstance(loaded, LocalPoint)
|
118
|
+
assert loaded == p
|
cocoindex/tests/test_typing.py
CHANGED
@@ -5,7 +5,6 @@ from collections.abc import Mapping, Sequence
|
|
5
5
|
from typing import Annotated, Any, Literal, NamedTuple, get_args, get_origin
|
6
6
|
|
7
7
|
import numpy as np
|
8
|
-
import pytest
|
9
8
|
from numpy.typing import NDArray
|
10
9
|
|
11
10
|
from cocoindex.typing import (
|
@@ -20,7 +19,10 @@ from cocoindex.typing import (
|
|
20
19
|
Vector,
|
21
20
|
VectorInfo,
|
22
21
|
analyze_type_info,
|
22
|
+
decode_engine_value_type,
|
23
23
|
encode_enriched_type,
|
24
|
+
encode_enriched_type_info,
|
25
|
+
encode_engine_value_type,
|
24
26
|
)
|
25
27
|
|
26
28
|
|
@@ -32,7 +34,7 @@ class SimpleDataclass:
|
|
32
34
|
|
33
35
|
class SimpleNamedTuple(NamedTuple):
|
34
36
|
name: str
|
35
|
-
value:
|
37
|
+
value: int
|
36
38
|
|
37
39
|
|
38
40
|
def test_ndarray_float32_no_dim() -> None:
|
@@ -427,3 +429,125 @@ def test_unknown_type() -> None:
|
|
427
429
|
typ = set
|
428
430
|
result = analyze_type_info(typ)
|
429
431
|
assert isinstance(result.variant, AnalyzedUnknownType)
|
432
|
+
|
433
|
+
|
434
|
+
# ========================= Encode/Decode Tests =========================
|
435
|
+
|
436
|
+
|
437
|
+
def encode_type_from_annotation(t: Any) -> dict[str, Any]:
|
438
|
+
"""Helper function to encode a Python type annotation to its dictionary representation."""
|
439
|
+
return encode_enriched_type_info(analyze_type_info(t))
|
440
|
+
|
441
|
+
|
442
|
+
def test_basic_types_encode_decode() -> None:
|
443
|
+
"""Test encode/decode roundtrip for basic Python types."""
|
444
|
+
test_cases = [
|
445
|
+
str,
|
446
|
+
int,
|
447
|
+
float,
|
448
|
+
bool,
|
449
|
+
bytes,
|
450
|
+
uuid.UUID,
|
451
|
+
datetime.date,
|
452
|
+
datetime.time,
|
453
|
+
datetime.datetime,
|
454
|
+
datetime.timedelta,
|
455
|
+
]
|
456
|
+
|
457
|
+
for typ in test_cases:
|
458
|
+
encoded = encode_type_from_annotation(typ)
|
459
|
+
decoded = decode_engine_value_type(encoded["type"])
|
460
|
+
reencoded = encode_engine_value_type(decoded)
|
461
|
+
assert reencoded == encoded["type"]
|
462
|
+
|
463
|
+
|
464
|
+
def test_vector_types_encode_decode() -> None:
|
465
|
+
"""Test encode/decode roundtrip for vector types."""
|
466
|
+
test_cases = [
|
467
|
+
NDArray[np.float32],
|
468
|
+
NDArray[np.float64],
|
469
|
+
NDArray[np.int64],
|
470
|
+
Vector[np.float32],
|
471
|
+
Vector[np.float32, Literal[128]],
|
472
|
+
Vector[str],
|
473
|
+
]
|
474
|
+
|
475
|
+
for typ in test_cases:
|
476
|
+
encoded = encode_type_from_annotation(typ)
|
477
|
+
decoded = decode_engine_value_type(encoded["type"])
|
478
|
+
reencoded = encode_engine_value_type(decoded)
|
479
|
+
assert reencoded == encoded["type"]
|
480
|
+
|
481
|
+
|
482
|
+
def test_struct_types_encode_decode() -> None:
|
483
|
+
"""Test encode/decode roundtrip for struct types."""
|
484
|
+
test_cases = [
|
485
|
+
SimpleDataclass,
|
486
|
+
SimpleNamedTuple,
|
487
|
+
]
|
488
|
+
|
489
|
+
for typ in test_cases:
|
490
|
+
encoded = encode_type_from_annotation(typ)
|
491
|
+
decoded = decode_engine_value_type(encoded["type"])
|
492
|
+
reencoded = encode_engine_value_type(decoded)
|
493
|
+
assert reencoded == encoded["type"]
|
494
|
+
|
495
|
+
|
496
|
+
def test_table_types_encode_decode() -> None:
|
497
|
+
"""Test encode/decode roundtrip for table types."""
|
498
|
+
test_cases = [
|
499
|
+
list[SimpleDataclass], # LTable
|
500
|
+
dict[str, SimpleDataclass], # KTable
|
501
|
+
]
|
502
|
+
|
503
|
+
for typ in test_cases:
|
504
|
+
encoded = encode_type_from_annotation(typ)
|
505
|
+
decoded = decode_engine_value_type(encoded["type"])
|
506
|
+
reencoded = encode_engine_value_type(decoded)
|
507
|
+
assert reencoded == encoded["type"]
|
508
|
+
|
509
|
+
|
510
|
+
def test_nullable_types_encode_decode() -> None:
|
511
|
+
"""Test encode/decode roundtrip for nullable types."""
|
512
|
+
test_cases = [
|
513
|
+
str | None,
|
514
|
+
int | None,
|
515
|
+
NDArray[np.float32] | None,
|
516
|
+
]
|
517
|
+
|
518
|
+
for typ in test_cases:
|
519
|
+
encoded = encode_type_from_annotation(typ)
|
520
|
+
decoded = decode_engine_value_type(encoded["type"])
|
521
|
+
reencoded = encode_engine_value_type(decoded)
|
522
|
+
assert reencoded == encoded["type"]
|
523
|
+
|
524
|
+
|
525
|
+
def test_annotated_types_encode_decode() -> None:
|
526
|
+
"""Test encode/decode roundtrip for annotated types."""
|
527
|
+
test_cases = [
|
528
|
+
Annotated[str, TypeAttr("key", "value")],
|
529
|
+
Annotated[NDArray[np.float32], VectorInfo(dim=256)],
|
530
|
+
Annotated[list[int], VectorInfo(dim=10)],
|
531
|
+
]
|
532
|
+
|
533
|
+
for typ in test_cases:
|
534
|
+
encoded = encode_type_from_annotation(typ)
|
535
|
+
decoded = decode_engine_value_type(encoded["type"])
|
536
|
+
reencoded = encode_engine_value_type(decoded)
|
537
|
+
assert reencoded == encoded["type"]
|
538
|
+
|
539
|
+
|
540
|
+
def test_complex_nested_encode_decode() -> None:
|
541
|
+
"""Test complex nested structure encode/decode roundtrip."""
|
542
|
+
|
543
|
+
# Create a complex nested structure using Python type annotations
|
544
|
+
@dataclasses.dataclass
|
545
|
+
class ComplexStruct:
|
546
|
+
embedding: NDArray[np.float32]
|
547
|
+
metadata: str | None
|
548
|
+
score: Annotated[float, TypeAttr("indexed", True)]
|
549
|
+
|
550
|
+
encoded = encode_type_from_annotation(ComplexStruct)
|
551
|
+
decoded = decode_engine_value_type(encoded["type"])
|
552
|
+
reencoded = encode_engine_value_type(decoded)
|
553
|
+
assert reencoded == encoded["type"]
|
cocoindex/typing.py
CHANGED
@@ -15,6 +15,7 @@ from typing import (
|
|
15
15
|
Protocol,
|
16
16
|
TypeVar,
|
17
17
|
overload,
|
18
|
+
Self,
|
18
19
|
)
|
19
20
|
|
20
21
|
import numpy as np
|
@@ -471,3 +472,209 @@ def resolve_forward_ref(t: Any) -> Any:
|
|
471
472
|
if isinstance(t, str):
|
472
473
|
return eval(t) # pylint: disable=eval-used
|
473
474
|
return t
|
475
|
+
|
476
|
+
|
477
|
+
# ========================= Engine Schema Types (Python mirror of Rust) =========================
|
478
|
+
|
479
|
+
|
480
|
+
@dataclasses.dataclass
|
481
|
+
class VectorTypeSchema:
|
482
|
+
element_type: "BasicValueType"
|
483
|
+
dimension: int | None
|
484
|
+
|
485
|
+
@staticmethod
|
486
|
+
def decode(obj: dict[str, Any]) -> "VectorTypeSchema":
|
487
|
+
return VectorTypeSchema(
|
488
|
+
element_type=BasicValueType.decode(obj["element_type"]),
|
489
|
+
dimension=obj.get("dimension"),
|
490
|
+
)
|
491
|
+
|
492
|
+
def encode(self) -> dict[str, Any]:
|
493
|
+
return {
|
494
|
+
"element_type": self.element_type.encode(),
|
495
|
+
"dimension": self.dimension,
|
496
|
+
}
|
497
|
+
|
498
|
+
|
499
|
+
@dataclasses.dataclass
|
500
|
+
class UnionTypeSchema:
|
501
|
+
variants: list["BasicValueType"]
|
502
|
+
|
503
|
+
@staticmethod
|
504
|
+
def decode(obj: dict[str, Any]) -> "UnionTypeSchema":
|
505
|
+
return UnionTypeSchema(
|
506
|
+
variants=[BasicValueType.decode(t) for t in obj["types"]]
|
507
|
+
)
|
508
|
+
|
509
|
+
def encode(self) -> dict[str, Any]:
|
510
|
+
return {"types": [variant.encode() for variant in self.variants]}
|
511
|
+
|
512
|
+
|
513
|
+
@dataclasses.dataclass
|
514
|
+
class BasicValueType:
|
515
|
+
"""
|
516
|
+
Mirror of Rust BasicValueType in JSON form.
|
517
|
+
|
518
|
+
For Vector and Union kinds, extra fields are populated accordingly.
|
519
|
+
"""
|
520
|
+
|
521
|
+
kind: Literal[
|
522
|
+
"Bytes",
|
523
|
+
"Str",
|
524
|
+
"Bool",
|
525
|
+
"Int64",
|
526
|
+
"Float32",
|
527
|
+
"Float64",
|
528
|
+
"Range",
|
529
|
+
"Uuid",
|
530
|
+
"Date",
|
531
|
+
"Time",
|
532
|
+
"LocalDateTime",
|
533
|
+
"OffsetDateTime",
|
534
|
+
"TimeDelta",
|
535
|
+
"Json",
|
536
|
+
"Vector",
|
537
|
+
"Union",
|
538
|
+
]
|
539
|
+
vector: VectorTypeSchema | None = None
|
540
|
+
union: UnionTypeSchema | None = None
|
541
|
+
|
542
|
+
@staticmethod
|
543
|
+
def decode(obj: dict[str, Any]) -> "BasicValueType":
|
544
|
+
kind = obj["kind"]
|
545
|
+
if kind == "Vector":
|
546
|
+
return BasicValueType(
|
547
|
+
kind=kind, # type: ignore[arg-type]
|
548
|
+
vector=VectorTypeSchema.decode(obj),
|
549
|
+
)
|
550
|
+
if kind == "Union":
|
551
|
+
return BasicValueType(
|
552
|
+
kind=kind, # type: ignore[arg-type]
|
553
|
+
union=UnionTypeSchema.decode(obj),
|
554
|
+
)
|
555
|
+
return BasicValueType(kind=kind) # type: ignore[arg-type]
|
556
|
+
|
557
|
+
def encode(self) -> dict[str, Any]:
|
558
|
+
result = {"kind": self.kind}
|
559
|
+
if self.kind == "Vector" and self.vector is not None:
|
560
|
+
result.update(self.vector.encode())
|
561
|
+
elif self.kind == "Union" and self.union is not None:
|
562
|
+
result.update(self.union.encode())
|
563
|
+
return result
|
564
|
+
|
565
|
+
|
566
|
+
@dataclasses.dataclass
|
567
|
+
class EnrichedValueType:
|
568
|
+
type: "ValueType"
|
569
|
+
nullable: bool = False
|
570
|
+
attrs: dict[str, Any] | None = None
|
571
|
+
|
572
|
+
@staticmethod
|
573
|
+
def decode(obj: dict[str, Any]) -> "EnrichedValueType":
|
574
|
+
return EnrichedValueType(
|
575
|
+
type=decode_engine_value_type(obj["type"]),
|
576
|
+
nullable=obj.get("nullable", False),
|
577
|
+
attrs=obj.get("attrs"),
|
578
|
+
)
|
579
|
+
|
580
|
+
def encode(self) -> dict[str, Any]:
|
581
|
+
result: dict[str, Any] = {"type": self.type.encode()}
|
582
|
+
if self.nullable:
|
583
|
+
result["nullable"] = True
|
584
|
+
if self.attrs is not None:
|
585
|
+
result["attrs"] = self.attrs
|
586
|
+
return result
|
587
|
+
|
588
|
+
|
589
|
+
@dataclasses.dataclass
|
590
|
+
class FieldSchema:
|
591
|
+
name: str
|
592
|
+
value_type: EnrichedValueType
|
593
|
+
|
594
|
+
@staticmethod
|
595
|
+
def decode(obj: dict[str, Any]) -> "FieldSchema":
|
596
|
+
return FieldSchema(name=obj["name"], value_type=EnrichedValueType.decode(obj))
|
597
|
+
|
598
|
+
def encode(self) -> dict[str, Any]:
|
599
|
+
result = self.value_type.encode()
|
600
|
+
result["name"] = self.name
|
601
|
+
return result
|
602
|
+
|
603
|
+
|
604
|
+
@dataclasses.dataclass
|
605
|
+
class StructSchema:
|
606
|
+
fields: list[FieldSchema]
|
607
|
+
description: str | None = None
|
608
|
+
|
609
|
+
@classmethod
|
610
|
+
def decode(cls, obj: dict[str, Any]) -> Self:
|
611
|
+
return cls(
|
612
|
+
fields=[FieldSchema.decode(f) for f in obj["fields"]],
|
613
|
+
description=obj.get("description"),
|
614
|
+
)
|
615
|
+
|
616
|
+
def encode(self) -> dict[str, Any]:
|
617
|
+
result: dict[str, Any] = {"fields": [field.encode() for field in self.fields]}
|
618
|
+
if self.description is not None:
|
619
|
+
result["description"] = self.description
|
620
|
+
return result
|
621
|
+
|
622
|
+
|
623
|
+
@dataclasses.dataclass
|
624
|
+
class StructType(StructSchema):
|
625
|
+
kind: Literal["Struct"] = "Struct"
|
626
|
+
|
627
|
+
def encode(self) -> dict[str, Any]:
|
628
|
+
result = super().encode()
|
629
|
+
result["kind"] = self.kind
|
630
|
+
return result
|
631
|
+
|
632
|
+
|
633
|
+
@dataclasses.dataclass
|
634
|
+
class TableType:
|
635
|
+
kind: Literal["KTable", "LTable"]
|
636
|
+
row: StructSchema
|
637
|
+
num_key_parts: int | None = None # Only for KTable
|
638
|
+
|
639
|
+
@staticmethod
|
640
|
+
def decode(obj: dict[str, Any]) -> "TableType":
|
641
|
+
row_obj = obj["row"]
|
642
|
+
row = StructSchema(
|
643
|
+
fields=[FieldSchema.decode(f) for f in row_obj["fields"]],
|
644
|
+
description=row_obj.get("description"),
|
645
|
+
)
|
646
|
+
return TableType(
|
647
|
+
kind=obj["kind"], # type: ignore[arg-type]
|
648
|
+
row=row,
|
649
|
+
num_key_parts=obj.get("num_key_parts"),
|
650
|
+
)
|
651
|
+
|
652
|
+
def encode(self) -> dict[str, Any]:
|
653
|
+
result: dict[str, Any] = {"kind": self.kind, "row": self.row.encode()}
|
654
|
+
if self.num_key_parts is not None:
|
655
|
+
result["num_key_parts"] = self.num_key_parts
|
656
|
+
return result
|
657
|
+
|
658
|
+
|
659
|
+
ValueType = BasicValueType | StructType | TableType
|
660
|
+
|
661
|
+
|
662
|
+
def decode_engine_field_schemas(objs: list[dict[str, Any]]) -> list[FieldSchema]:
|
663
|
+
return [FieldSchema.decode(o) for o in objs]
|
664
|
+
|
665
|
+
|
666
|
+
def decode_engine_value_type(obj: dict[str, Any]) -> ValueType:
|
667
|
+
kind = obj["kind"]
|
668
|
+
if kind == "Struct":
|
669
|
+
return StructType.decode(obj)
|
670
|
+
|
671
|
+
if kind in TABLE_TYPES:
|
672
|
+
return TableType.decode(obj)
|
673
|
+
|
674
|
+
# Otherwise it's a basic value
|
675
|
+
return BasicValueType.decode(obj)
|
676
|
+
|
677
|
+
|
678
|
+
def encode_engine_value_type(value_type: ValueType) -> dict[str, Any]:
|
679
|
+
"""Encode a ValueType to its dictionary representation."""
|
680
|
+
return value_type.encode()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: cocoindex
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.13
|
4
4
|
Classifier: Development Status :: 3 - Alpha
|
5
5
|
Classifier: License :: OSI Approved :: Apache Software License
|
6
6
|
Classifier: Operating System :: OS Independent
|
@@ -16,6 +16,7 @@ Classifier: Topic :: Text Processing :: Indexing
|
|
16
16
|
Classifier: Intended Audience :: Developers
|
17
17
|
Classifier: Natural Language :: English
|
18
18
|
Classifier: Typing :: Typed
|
19
|
+
Requires-Dist: typing-extensions>=4.12 ; python_full_version < '3.13'
|
19
20
|
Requires-Dist: click>=8.1.8
|
20
21
|
Requires-Dist: rich>=14.0.0
|
21
22
|
Requires-Dist: python-dotenv>=1.1.0
|
@@ -29,11 +30,14 @@ Requires-Dist: mypy ; extra == 'dev'
|
|
29
30
|
Requires-Dist: pre-commit ; extra == 'dev'
|
30
31
|
Requires-Dist: sentence-transformers>=3.3.1 ; extra == 'embeddings'
|
31
32
|
Requires-Dist: colpali-engine ; extra == 'colpali'
|
33
|
+
Requires-Dist: lancedb>=0.25.0 ; extra == 'lancedb'
|
32
34
|
Requires-Dist: sentence-transformers>=3.3.1 ; extra == 'all'
|
33
35
|
Requires-Dist: colpali-engine ; extra == 'all'
|
36
|
+
Requires-Dist: lancedb>=0.25.0 ; extra == 'all'
|
34
37
|
Provides-Extra: dev
|
35
38
|
Provides-Extra: embeddings
|
36
39
|
Provides-Extra: colpali
|
40
|
+
Provides-Extra: lancedb
|
37
41
|
Provides-Extra: all
|
38
42
|
License-File: THIRD_PARTY_NOTICES.html
|
39
43
|
Summary: With CocoIndex, users declare the transformation, CocoIndex creates & maintains an index, and keeps the derived index up to date based on source update, with minimal computation and changes.
|
@@ -227,6 +231,7 @@ It defines an index flow like this:
|
|
227
231
|
| [Google Drive Text Embedding](examples/gdrive_text_embedding) | Index text documents from Google Drive |
|
228
232
|
| [Docs to Knowledge Graph](examples/docs_to_knowledge_graph) | Extract relationships from Markdown documents and build a knowledge graph |
|
229
233
|
| [Embeddings to Qdrant](examples/text_embedding_qdrant) | Index documents in a Qdrant collection for semantic search |
|
234
|
+
| [Embeddings to LanceDB](examples/text_embedding_lancedb) | Index documents in a LanceDB collection for semantic search |
|
230
235
|
| [FastAPI Server with Docker](examples/fastapi_server_docker) | Run the semantic search server in a Dockerized FastAPI setup |
|
231
236
|
| [Product Recommendation](examples/product_recommendation) | Build real-time product recommendations with LLM and graph database|
|
232
237
|
| [Image Search with Vision API](examples/image_search) | Generates detailed captions for images using a vision model, embeds them, enables live-updating semantic search via FastAPI and served on a React frontend|
|
@@ -1,34 +1,37 @@
|
|
1
|
-
cocoindex-0.2.
|
2
|
-
cocoindex-0.2.
|
3
|
-
cocoindex-0.2.
|
4
|
-
cocoindex-0.2.
|
1
|
+
cocoindex-0.2.13.dist-info/METADATA,sha256=08dUNFSA-_C_GyIUPTzNCV5ss-L-GP8r07ucSnlU7N4,13316
|
2
|
+
cocoindex-0.2.13.dist-info/WHEEL,sha256=pQhpX1zEYym7lHVMSudaqVXS44siTf8XBrjmsFdZ39M,108
|
3
|
+
cocoindex-0.2.13.dist-info/entry_points.txt,sha256=_NretjYVzBdNTn7dK-zgwr7YfG2afz1u1uSE-5bZXF8,46
|
4
|
+
cocoindex-0.2.13.dist-info/licenses/THIRD_PARTY_NOTICES.html,sha256=kOcN_-Ew74skSjMDUYvpRfdbB2pO24VPcbup3dwagb4,717769
|
5
5
|
cocoindex/__init__.py,sha256=AsoNLBgjJ-1AEKtwTnENJM9dEilHTq6rJ4qWUzGKSdc,2428
|
6
|
-
cocoindex/_engine.abi3.so,sha256=
|
7
|
-
cocoindex/auth_registry.py,sha256=
|
6
|
+
cocoindex/_engine.abi3.so,sha256=cCYiapj8nx4ACZ9PtfNGczX0csa8P1l-y02XOVR1zCk,70905432
|
7
|
+
cocoindex/auth_registry.py,sha256=_DOIY42C79joLCY_XczHwP5uebkmSavweoAHc0L3hQY,1334
|
8
8
|
cocoindex/cli.py,sha256=69X30bFTFdM7c0_6lgIHR19CeQ7UEkobEQYihy8IdOQ,21599
|
9
|
-
cocoindex/convert.py,sha256=
|
10
|
-
cocoindex/flow.py,sha256=
|
9
|
+
cocoindex/convert.py,sha256=itkUBCriOk8fdauahHRqJ-L8mnHehNZsBe_FouN0K1Q,28695
|
10
|
+
cocoindex/flow.py,sha256=Vk72dX_svfpinvsolQ11aw6YDqbzaafrAi7xrQHo1i0,39844
|
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=c1xzoiWoPb6PYiCQAUsyzMRJwPvWaC3o5emPk38oY-4,26551
|
16
16
|
cocoindex/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
|
-
cocoindex/query_handler.py,sha256=
|
17
|
+
cocoindex/query_handler.py,sha256=X-SQT71LHiOOXn6-TJlQcGodJk-iT8p_1TcIMvRLBRI,1344
|
18
18
|
cocoindex/runtime.py,sha256=4NxcltaDZvA3RR3Pnt6gH_f99jcWSyMH_1Xi5BjbtwY,1342
|
19
19
|
cocoindex/setting.py,sha256=1Dx8ktjwf-8BiXrbsmfn5Mzudb2SQYqFdRnSNGVKaLk,4960
|
20
20
|
cocoindex/setup.py,sha256=7uIHKN4FOCuoidPXcKyGTrkqpkl9luL49-6UcnMxYzw,3068
|
21
21
|
cocoindex/sources.py,sha256=FYz7cWYasLGDaYoIEQ1dF2uprgUETHWsTIrIS7n6pQE,3188
|
22
22
|
cocoindex/subprocess_exec.py,sha256=r1xO84uek4VP4I6i87JMwsH5xFm3vKW0ABvgn0jskt4,10088
|
23
|
-
cocoindex/targets.py,sha256=
|
23
|
+
cocoindex/targets/__init__.py,sha256=HQG7I4U0xQhHiYctiUvwEBLxT2727oHP3xwrqotjmhk,78
|
24
|
+
cocoindex/targets/_engine_builtin_specs.py,sha256=DM7vyO0pkoukA-aBbvm_J4irgXhXIEqWdp-hwVpVRU4,2800
|
25
|
+
cocoindex/targets/lancedb.py,sha256=pEHEBCOEe358e14cqAI1SytUTBCgRkYCsv9fJE7biTA,15440
|
24
26
|
cocoindex/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
-
cocoindex/tests/test_convert.py,sha256=
|
27
|
+
cocoindex/tests/test_convert.py,sha256=pG1AkEdIKSRE0trMV2dQ6VSQEqQJnPTJzfQCVrZSz8w,50791
|
28
|
+
cocoindex/tests/test_load_convert.py,sha256=XHuXhgLcazniEYrhoz_L5RFvgUwu-iy3EB9zgR6p95A,3339
|
26
29
|
cocoindex/tests/test_optional_database.py,sha256=snAmkNa6wtOSaxoZE1HgjvL5v_ylitt3Jt_9df4Cgdc,8506
|
27
30
|
cocoindex/tests/test_transform_flow.py,sha256=G69w-n-vnCTo3r9hVIk2lJNAQEkGUA7PZfHsXna3oS0,6030
|
28
|
-
cocoindex/tests/test_typing.py,sha256=
|
31
|
+
cocoindex/tests/test_typing.py,sha256=JoR-oMK-ZWjOGQi0pH5Etg5jp4oL_JSIreGBH247GCg,16291
|
29
32
|
cocoindex/tests/test_validation.py,sha256=X6AQzVs-hVKIXcrHMEMQnhfUE8at7iXQnPq8nHNhZ2Q,4543
|
30
|
-
cocoindex/typing.py,sha256=
|
33
|
+
cocoindex/typing.py,sha256=jZO3meRVL_RsFdhj8Sx6gWF-Z207VhoPtb1ZmqzAnH0,19974
|
31
34
|
cocoindex/user_app_loader.py,sha256=bc3Af-gYRxJ9GpObtpjegZY855oQBCv5FGkrkWV2yGY,1873
|
32
35
|
cocoindex/utils.py,sha256=hUhX-XV6XGCtJSEIpBOuDv6VvqImwPlgBxztBTw7u0U,598
|
33
36
|
cocoindex/validation.py,sha256=PZnJoby4sLbsmPv9fOjOQXuefjfZ7gmtsiTGU8SH-tc,3090
|
34
|
-
cocoindex-0.2.
|
37
|
+
cocoindex-0.2.13.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.13</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>
|
@@ -10673,38 +10673,6 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
10673
10673
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
10674
10674
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
10675
10675
|
THE SOFTWARE.</pre>
|
10676
|
-
</li>
|
10677
|
-
<li class="license">
|
10678
|
-
<h3 id="MIT">MIT License</h3>
|
10679
|
-
<h4>Used by:</h4>
|
10680
|
-
<ul class="license-used-by">
|
10681
|
-
<li><a href=" https://github.com/tree-sitter/tree-sitter-scala ">tree-sitter-scala 0.24.0</a></li>
|
10682
|
-
</ul>
|
10683
|
-
<pre class="license-text">(The MIT License)
|
10684
|
-
|
10685
|
-
Copyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>
|
10686
|
-
|
10687
|
-
Permission is hereby granted, free of charge, to any person
|
10688
|
-
obtaining a copy of this software and associated documentation
|
10689
|
-
files (the "Software"), to deal in the Software without
|
10690
|
-
restriction, including without limitation the rights to use,
|
10691
|
-
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10692
|
-
copies of the Software, and to permit persons to whom the
|
10693
|
-
Software is furnished to do so, subject to the following
|
10694
|
-
conditions:
|
10695
|
-
|
10696
|
-
The above copyright notice and this permission notice shall be
|
10697
|
-
included in all copies or substantial portions of the Software.
|
10698
|
-
|
10699
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
10700
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
10701
|
-
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
10702
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
10703
|
-
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
10704
|
-
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
10705
|
-
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
10706
|
-
OTHER DEALINGS IN THE SOFTWARE.
|
10707
|
-
</pre>
|
10708
10676
|
</li>
|
10709
10677
|
<li class="license">
|
10710
10678
|
<h3 id="MIT">MIT License</h3>
|
@@ -12299,6 +12267,32 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
12299
12267
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
12300
12268
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
12301
12269
|
THE SOFTWARE.
|
12270
|
+
</pre>
|
12271
|
+
</li>
|
12272
|
+
<li class="license">
|
12273
|
+
<h3 id="MIT">MIT License</h3>
|
12274
|
+
<h4>Used by:</h4>
|
12275
|
+
<ul class="license-used-by">
|
12276
|
+
<li><a href=" https://github.com/tree-sitter/tree-sitter-scala ">tree-sitter-scala 0.24.0</a></li>
|
12277
|
+
</ul>
|
12278
|
+
<pre class="license-text">This software is released under the MIT license:
|
12279
|
+
|
12280
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
12281
|
+
this software and associated documentation files (the "Software"), to deal in
|
12282
|
+
the Software without restriction, including without limitation the rights to
|
12283
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
12284
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
12285
|
+
subject to the following conditions:
|
12286
|
+
|
12287
|
+
The above copyright notice and this permission notice shall be included in all
|
12288
|
+
copies or substantial portions of the Software.
|
12289
|
+
|
12290
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
12291
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
12292
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
12293
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
12294
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
12295
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
12302
12296
|
</pre>
|
12303
12297
|
</li>
|
12304
12298
|
<li class="license">
|
File without changes
|
File without changes
|