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)