概述
当把文本拆分成chunk后,dify就会把一个个的chunk通过大模型计算成嵌入向量,并保存到向量数据库中。其实,在创建嵌入向量时分成了两步:
第一步,是批量计算document的嵌入向量,并把嵌入向量添加到数据库(注意:这里的数据库是关系型数据库,而非向量数据库)中;这一步的主要目的是,把计算好的嵌入向量保存起来,下次使用时直接获取,避免重复计算。
第二步:把上一步计算出来的嵌入向量添加到向量数据库中。这一步的主要目的是,把嵌入向量添加到向量数据库中,供后续的嵌入向量查询使用,通过向量库来找到相似度最接近的文本块。
代码如下:
def create(self, texts: Optional[list] = None, **kwargs):
if texts:
# 使用嵌入大模型来计算文本的嵌入向量
embeddings = self._embeddings.embed_documents([document.page_content for document in texts])
# 把文本向量更新到向量数据库中
self._vector_processor.create(texts=texts, embeddings=embeddings, **kwargs)
第一步构建并缓存嵌入向量是在CacheEmbedding类中完成,本文主要分析第一步的实现逻辑。
CacheEmbedding的创建
这里的_embeddings
是在创建Vector对象时,通过以下函数获取。该函数做了2件事:(1)构建嵌入模型实例,实例中包括了使用嵌入模型的各种参数,和各种元数据信息。(2)然后创建一个CacheEmbedding对象,在构建CacheEmbedding对象是,会把刚才构建的嵌入模型对象传入其中。所以,_embeddings其实是一个CacheEmbedding实例。
def _get_embeddings(self) -> Embeddings:
model_manager = ModelManager()
embedding_model = model_manager.get_model_instance(
tenant_id=self._dataset.tenant_id,
provider=self._dataset.embedding_model_provider,
model_type=ModelType.TEXT_EMBEDDING,
model=self._dataset.embedding_model,
)
return CacheEmbedding(embedding_model)
这样,焦点就集中在CacheEmbedding类是如何实现。
CacheEmbedding说明
该类有两个方法:(1)embed_documents:根据传入的文本来构建嵌入向量。(2)embed_query函数:根据传入的文本来查询最合适的嵌入向量。
embed_documents函数概要
- 函数声明:
def embed_documents(self, texts: list[str]) -> list[list[float]]:
- 功能
把传入的文档列表(也就是:list[str])转换成嵌入向量(也就是类型:list[list[float]])。若缓存中已经存在str对应的嵌入向量,则不需要处理,则直接返回嵌入向量的值。否则,需要批量把文档处理成嵌入向量,