将数据模型序列化到不同存储以及从不同存储进行序列化(预览版)
为了使数据模型存储在数据库中,需要将其转换为数据库可以理解的格式。 不同的数据库需要不同的存储架构和格式。 有些具有需要遵守的严格架构,而另一些则允许用户定义架构。
映射选项
语义内核提供的矢量存储连接器提供了多种实现此映射的方法。
内置映射器
语义内核提供的矢量存储连接器具有内置映射器,可以将您的数据模型与数据库架构进行双向映射。 有关内置映射器如何为每个数据库映射数据的详细信息,请参阅每个连接器 的
自定义映射器
语义内核提供的向量存储连接器具有提供将自定义映射器与 VectorStoreRecordDefinition
结合使用的功能。 在这种情况下,VectorStoreRecordDefinition
可能与提供的数据模型不同。
VectorStoreRecordDefinition
用于定义数据库架构,而开发人员使用数据模型与矢量存储进行交互。
在这种情况下,需要自定义映射器才能从数据模型映射到由 VectorStoreRecordDefinition
定义的自定义数据库架构。
提示
有关如何创建自定义映射器的示例,请参阅 如何为 Vector Store 连接器生成自定义映射器。
为了使数据模型定义为 类 或 要存储在数据库中的定义 ,需要序列化为数据库可以理解的格式。
可通过两种方式完成,可以使用语义内核提供的内置序列化或提供自己的序列化逻辑。
以下两个关系图显示了数据模型在与存储模型之间进行序列化和反序列化的过程。
序列化流(用于 Upsert)
反序列化流(用于获取和搜索)
标有 *(在这两个关系图中)的步骤由特定连接器的开发人员实现,并且对于每个商店都是不同的。 标记为 ** 的步骤(在这两个关系图中)都作为记录上的方法提供,或者作为记录定义的一部分提供,这始终由用户提供,有关详细信息,请参阅 直接序列化。
(反)序列化方法
直接序列化(从数据模型到存储模型)
直接序列化是确保完全控制模型序列化方式和优化性能的最佳方式。 缺点是,它特定于一个数据存储,因此,在使用时,与采用相同数据模型的不同存储之间切换并不容易。
可以通过在数据模型中实现遵循 SerializeMethodProtocol
协议的方法,或者将遵循 SerializeFunctionProtocol
的函数添加到记录定义中,这两种方法都可以在 semantic_kernel/data/vector_store_model_protocols.py
中找到。
当其中一个函数存在时,它将用于将数据模型直接序列化到存储模型。
你甚至可以只实现两种方法中的一种,并使用内置的(反)序列化处理另一个方向。例如,当处理一个不在你控制范围内创建的集合时,这可能会非常有用,并且你需要对反序列化的方式进行一些定制(而且无论如何也无法进行更新插入操作)。
内置序列化和反序列化(数据模型到字典对象、字典对象到存储模型,反之亦然)
内置序列化首先将数据模型转换为字典,然后将其序列化为存储理解的模型,对于每个存储区(不同且定义为内置连接器的一部分)来完成。 反序列化按相反的顺序完成。
序列化步骤 1:数据模型到字典
根据你拥有的数据模型类型,这些步骤以不同的方式完成。 可通过四种方式尝试将数据模型序列化为字典:
- 定义上的
to_dict
方法(与数据模型to_dict属性一致,遵循ToDictFunctionProtocol
) - 检查记录是否为
ToDictMethodProtocol
并使用to_dict
方法 - 检查记录是否为 Pydantic 模型并使用模型的
model_dump
,有关详细信息,请参阅以下说明。 - 遍历定义中的字段并创建字典
序列化步骤 2:字典储存模型
连接器必须提供一种方法,以便将字典转换为存储模型。 这由连接器的开发人员完成,对于每个商店都是不同的。
反序列化步骤 1:将模型存储到字典
连接器必须提供一种方法,以便将存储模型转换为字典。 这由连接器的开发人员完成,对于每个商店都是不同的。
反序列化步骤 2:字典到数据模型
反序列化按相反的顺序完成,它会尝试以下选项:
- 定义中的
from_dict
方法(与数据模型的 from_dict 属性对齐,遵循FromDictFunctionProtocol
)。 - 检查记录是否为
FromDictMethodProtocol
并使用from_dict
方法 - 检查记录是否为 Pydantic 模型并使用模型的
model_validate
,有关详细信息,请参阅以下说明。 - 循环遍历定义中的字段并设置其值,然后将这个字典作为命名参数传递给数据模型的构造函数(除非数据模型本身是一个字典,在这种情况下,它将按原样返回)。
注意
将 Pydantic 与内置序列化配合使用
使用 Pydantic BaseModel 定义模型时,它将使用 model_dump
和 model_validate
方法将数据模型序列化和反序列化到听写。 这是通过使用不带任何参数的 model_dump 方法来完成的,如果您希望对此进行控制,建议在您的数据模型上实现 ToDictMethodProtocol
,因为系统会优先尝试该方法。
矢量的序列化
在数据模型中有矢量时,它需要是浮点列表或 ints 列表,因为这是大多数存储所需的,如果希望类以不同的格式存储向量,则可以使用serialize_function
注释中deserialize_function
定义的和VectorStoreRecordVectorField
定义。 例如,对于 numpy 数组,可以使用以下注释:
import numpy as np
vector: Annotated[
np.ndarray | None,
VectorStoreRecordVectorField(
dimensions=1536,
serialize_function=np.ndarray.tolist,
deserialize_function=np.array,
),
] = None
如果您确实使用可以处理原生 numpy 数组的矢量存储,并且不希望它们来回转换,您应该为模型和该存储建立 直接序列化和反序列化 方法。
注意
仅在使用内置序列化时才会用到它,而使用直接序列化时,你可以以任何方式处理向量。
即将推出
更多信息即将推出。