c889a57b6b
Test Suites / Build CI Environment (push) Has been cancelled
Test Suites / Basic Tests (push) Has been cancelled
Test Suites / End-to-End Tests (push) Has been cancelled
Test Suites / CLI Tests (push) Has been cancelled
Test Suites / Slow End-to-End Tests (push) Has been cancelled
Test Suites / Graph Database Tests (push) Has been cancelled
Test Suites / Vector DB Tests (push) Has been cancelled
Test Suites / Temporal Graph Test (push) Has been cancelled
Test Suites / Search Test on Different DBs (push) Has been cancelled
Test Suites / Example Tests (push) Has been cancelled
Test Suites / Notebook Tests (push) Has been cancelled
Test Suites / OS and Python Tests Ubuntu (push) Has been cancelled
Test Suites / OS and Python Tests Extended (push) Has been cancelled
Test Suites / LLM Test Suite (push) Has been cancelled
Test Suites / S3 File Storage Test (push) Has been cancelled
Test Suites / Run Integration Tests (push) Has been cancelled
Test Suites / MCP Tests (push) Has been cancelled
Test Suites / Docker Compose Test (push) Has been cancelled
Test Suites / Docker CI test (push) Has been cancelled
Test Suites / Relational DB Migration Tests (push) Has been cancelled
Test Suites / Distributed Cognee Test (push) Has been cancelled
Test Suites / DB Examples Tests (push) Has been cancelled
Test Suites / Test Completion Status (push) Has been cancelled
Test Suites / Claude Code Review (push) Has been cancelled
Test Suites / basic checks (push) Has been cancelled
build | Build and Push Cognee MCP Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
build | Build and Push Docker Image to dockerhub / docker-build-and-push (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.11) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Core Functionality (3.12) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (kuzu, kuzu) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges with Different Graph Databases (neo4j, neo4j) (push) Has been cancelled
Weighted Edges Tests / Test Weighted Edges Examples (push) Has been cancelled
Weighted Edges Tests / Code Quality for Weighted Edges (push) Has been cancelled
146 lines
5.1 KiB
Python
146 lines
5.1 KiB
Python
import asyncio
|
|
|
|
from cognee.shared.logging_utils import get_logger
|
|
from cognee.infrastructure.databases.vector import get_vector_engine_async
|
|
from cognee.infrastructure.engine import DataPoint
|
|
|
|
logger = get_logger("index_data_points")
|
|
|
|
|
|
async def index_data_points(data_points: list[DataPoint], vector_engine=None):
|
|
"""Index data points in the vector engine by creating embeddings for specified fields.
|
|
|
|
Each data point is indexed individually. A semaphore (sized to the embedding
|
|
engine's batch_size) keeps that many calls in flight at all times, so as one
|
|
completes the next starts immediately without waiting for an entire batch to drain.
|
|
|
|
Args:
|
|
data_points: List of DataPoint objects to index. Each DataPoint's metadata must
|
|
contain an 'index_fields' list specifying which fields to embed.
|
|
vector_engine: Optional pre-created vector engine. Falls back to
|
|
``get_vector_engine_async()`` when not supplied.
|
|
|
|
Returns:
|
|
The original data_points list.
|
|
"""
|
|
data_points_by_type = {}
|
|
|
|
vector_engine = vector_engine or await get_vector_engine_async()
|
|
|
|
for data_point in data_points:
|
|
# Skip non-DataPoint objects (e.g. CogneeGraph) that may be
|
|
# passed through the memify pipeline without metadata.
|
|
if not hasattr(data_point, "metadata") or not data_point.metadata:
|
|
continue
|
|
|
|
data_point_type = type(data_point)
|
|
type_name = data_point_type.__name__
|
|
|
|
for field_name in data_point.metadata["index_fields"]:
|
|
if getattr(data_point, field_name, None) is None:
|
|
continue
|
|
|
|
if type_name not in data_points_by_type:
|
|
data_points_by_type[type_name] = {}
|
|
|
|
if field_name not in data_points_by_type[type_name]:
|
|
await vector_engine.create_vector_index(type_name, field_name)
|
|
data_points_by_type[type_name][field_name] = []
|
|
|
|
indexed_data_point = data_point.model_copy()
|
|
indexed_data_point.metadata["index_fields"] = [field_name]
|
|
data_points_by_type[type_name][field_name].append(indexed_data_point)
|
|
|
|
batch_size = vector_engine.embedding_engine.get_batch_size()
|
|
semaphore = asyncio.Semaphore(4)
|
|
|
|
async def _index_batch(type_name, field_name, batch):
|
|
async with semaphore:
|
|
await vector_engine.index_data_points(type_name, field_name, batch)
|
|
|
|
tasks = []
|
|
for type_name, fields in data_points_by_type.items():
|
|
for field_name, points in fields.items():
|
|
for i in range(0, len(points), batch_size):
|
|
batch = points[i : i + batch_size]
|
|
tasks.append(asyncio.create_task(_index_batch(type_name, field_name, batch)))
|
|
|
|
await asyncio.gather(*tasks)
|
|
|
|
return data_points
|
|
|
|
|
|
async def get_data_points_from_model(
|
|
data_point: DataPoint, added_data_points=None, visited_properties=None
|
|
) -> list[DataPoint]:
|
|
data_points = []
|
|
added_data_points = added_data_points or {}
|
|
visited_properties = visited_properties or {}
|
|
|
|
for field_name, field_value in data_point:
|
|
if isinstance(field_value, DataPoint):
|
|
property_key = f"{str(data_point.id)}{field_name}{str(field_value.id)}"
|
|
|
|
if property_key in visited_properties:
|
|
return []
|
|
|
|
visited_properties[property_key] = True
|
|
|
|
new_data_points = await get_data_points_from_model(
|
|
field_value, added_data_points, visited_properties
|
|
)
|
|
|
|
for new_point in new_data_points:
|
|
if str(new_point.id) not in added_data_points:
|
|
added_data_points[str(new_point.id)] = True
|
|
data_points.append(new_point)
|
|
|
|
if (
|
|
isinstance(field_value, list)
|
|
and len(field_value) > 0
|
|
and isinstance(field_value[0], DataPoint)
|
|
):
|
|
for field_value_item in field_value:
|
|
property_key = f"{str(data_point.id)}{field_name}{str(field_value_item.id)}"
|
|
|
|
if property_key in visited_properties:
|
|
return []
|
|
|
|
visited_properties[property_key] = True
|
|
|
|
new_data_points = await get_data_points_from_model(
|
|
field_value_item, added_data_points, visited_properties
|
|
)
|
|
|
|
for new_point in new_data_points:
|
|
if str(new_point.id) not in added_data_points:
|
|
added_data_points[str(new_point.id)] = True
|
|
data_points.append(new_point)
|
|
|
|
if str(data_point.id) not in added_data_points:
|
|
data_points.append(data_point)
|
|
|
|
return data_points
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
class Car(DataPoint):
|
|
model: str
|
|
color: str
|
|
metadata: dict = {"index_fields": ["name"]}
|
|
|
|
class Person(DataPoint):
|
|
name: str
|
|
age: int
|
|
owns_car: list[Car]
|
|
metadata: dict = {"index_fields": ["name"]}
|
|
|
|
car1 = Car(model="Tesla Model S", color="Blue")
|
|
car2 = Car(model="Toyota Camry", color="Red")
|
|
person = Person(name="John", age=30, owns_car=[car1, car2])
|
|
|
|
data_points = get_data_points_from_model(person)
|
|
|
|
print(data_points)
|