
近年来,使用嵌入来提高信息检索的相关性和准确性已经显著增长。像 Elasticsearch 这样的工具已经发展到支持这种类型的数据,通过专门的字段类型如 dense vectors、sparse vectors 和 semantic text。然而,要想取得好的效果,关键是要了解如何将嵌入正确映射到可用的 Elasticsearch 字段类型:semantic_text、dense_vector 和 sparse_vector。
本文将讨论这些字段类型、使用场景以及它们与嵌入生成和使用策略之间的关系,包括在索引和查询过程中的应用。
Elasticsearch 中的 dense_vector 字段类型用于存储密集向量,这些向量是文本的数值表示,其中几乎所有维度都很重要。这些向量由语言模型生成,比如 OpenAI、Cohere 和 Hugging Face,旨在捕捉文本的整体语义意义,即使它与其他文档没有共享确切的术语。
在 Elasticsearch 中,密集向量的维度可以根据所使用的模型达到 4096。例如,all-MiniLM-L6-v2 模型生成 384 维的向量,而 OpenAI 的 text-embedding-ada-002 生成 1536 维的向量。
当需要更大控制时,比如使用预生成的向量、应用自定义相似性函数或与外部模型集成时,dense_vector 字段通常被作为存储此类嵌入的默认类型。
密集向量非常适合于捕捉句子、段落或整个文档之间的语义相似性。它们在需要比较文本的整体意义时效果很好,即使文本之间没有共享相同的术语。
当你已经有一个使用 OpenAI、Cohere 或 Hugging Face 等模型的外部嵌入生成管道,并且只想手动存储和查询这些向量时,dense vector 字段是理想的选择。这种字段类型与嵌入模型高度兼容,并在生成和查询时提供完全的灵活性,使你能够控制向量的生成、索引和使用方式。
此外,它支持不同形式的语义搜索,如 KNN 或 script_score 查询,这对需要调整排名逻辑的情况非常有用。这些可能性使得 dense vector 成为 RAG(检索增强生成)、推荐系统和基于相似性的个性化搜索等应用的理想选择。
最后,该字段允许你自定义相关性逻辑,使用诸如 cosineSimilarity、dotProduct 或 l2norm 之类的函数来根据你的用例需求调整排名。
对于需要灵活性、自定义和与高级用例兼容性的用户来说,dense vector 是最佳选择。
定义为 dense_vector 的字段的搜索使用 k-近邻(k-nearest neighbor)查询。这种查询负责找到那些密集向量最接近查询向量的文档。下面是如何对 dense vector 字段应用 Knn 查询的示例:
{
"knn": {
"field": "my_dense_vector",
"k": 10,
"num_candidates": 50,
"query_vector": [/* 由模型生成的向量 */]
}
}除了 Knn 查询,如果需要自定义文档评分,还可以使用 script_score 查询,将其与向量比较函数如 cosineSimilarity、dotProduct 或 l2norm 相结合,以更受控的方式计算相关性。请参见示例:
{
"script_score": {
"query": { "match_all": {} },
"script": {
"source": "cosineSimilarity(params.query_vector, 'my_dense_vector') + 1.0",
"params": {
"query_vector": [/* 向量 */]
}
}
}
}如果你想深入了解,我推荐阅读文章如何在 Elasticsearch 中设置向量搜索。
sparse_vector 字段类型用于存储稀疏向量,这些向量是数值表示,其中大多数值为零,只有少数术语具有显著权重。这种类型的向量在基于术语的模型如 SPLADE 或 ELSER(Elastic Learned Sparse EncodeR)中很常见。
稀疏向量在需要更精确的词汇搜索而不牺牲语义智能时是理想的选择。它们以标记/值对的形式表示文本,仅突出显示最相关的术语及其相关权重,从而提供清晰性、控制和效率。
当你基于术语生成向量时,比如在 ELSER 或 SPLADE 模型中,稀疏向量类型尤其有用,这些模型根据每个标记在文本中的相对重要性分配不同的权重。
在需要控制查询中特定词语的影响时,稀疏向量类型允许你手动调整术语的权重,以优化结果的排名。
主要优势包括搜索的透明性,因为可以清楚地了解为什么某个文档被认为是相关的,以及存储效率,因为只有具有非零值的标记被保存,而不是像密集向量那样存储所有维度。
此外,稀疏向量是混合搜索策略的理想补充,甚至可以与密集向量结合使用,以结合词汇精度和语义理解。
sparse_vector 查询允许你根据以标记/值格式的查询向量搜索文档。请参见下面的查询示例:
{
"query": {
"sparse_vector": {
"field": "field_sparse",
"query_vector": {
"token1": 0.5,
"token2": 0.3,
"token3": 0.2
}
}
}
}如果你希望使用训练模型,可以使用一个推理端点,该端点会自动将查询文本转换为稀疏向量:
{
"query": {
"sparse_vector": {
"field": "field_sparse",
"inference_id": "生成标记/权重的推理ID",
"query": "搜索文本"
}
}
}要进一步探索这个主题,我建议阅读使用训练的机器学习模型理解稀疏向量嵌入。
semantic_text 字段类型是 Elasticsearch 中使用语义搜索的最简单和直接的方法。它通过一个推理端点在索引和查询时自动处理嵌入生成。这意味着你不必手动生成或存储向量。
semantic_text 字段是 Elasticsearch 中采用语义搜索的最简单和直接的方法。对于那些希望以最小的技术努力开始并且不想手动处理向量的人来说,它是理想的选择。这个字段自动化了嵌入生成和向量搜索映射等步骤,使设置更快更方便。
当你重视简单性和抽象时,应考虑使用 semantic_text,因为它消除了手动配置映射、嵌入生成和摄取管道的复杂性。只需选择推理模型,Elasticsearch 就会处理其余部分。
主要优势包括自动嵌入生成,在索引和查询时进行,以及即用型映射,它预先配置为支持所选推理模型。
此外,该字段提供对长文本的自动分割(文本分块)的原生支持,允许将大型文本分割成较小的段落,每个段落都有自己的嵌入,从而提高搜索精度。这大大提高了生产力,特别是对于希望快速交付价值而不处理语义搜索底层工程的团队。
然而,虽然 semantic_text 提供速度和简单性,但这种方法也有一些限制。它允许使用市场标准模型,只要它们在 Elasticsearch 中可用作推理端点。但不支持外部生成的嵌入,这在 dense_vector 字段中是可能的。
如果你需要更多控制向量的生成方式,想使用自己的嵌入,或需要结合多个字段以进行高级策略,dense_vector 和 sparse_vector 字段提供了更为定制或特定领域场景所需的灵活性。
在 semantic_text 出现之前,根据嵌入类型(密集或稀疏)需要使用不同的查询。稀疏字段使用 sparse_vector 查询,而密集向量字段需要 KNN 查询。
有了 semantic text 类型,搜索使用语义查询,它自动生成查询向量并将其与索引文档的嵌入进行比较。semantic_text 类型允许你定义一个推理端点来嵌入查询,但如果未指定,将对查询应用索引时使用的相同端点。
{
"query": {
"semantic": {
"field": "semantic_text_field",
"query": "搜索文本"
}
}
}要了解更多,我建议阅读文章Elasticsearch 新的 semantic_text 映射:简化语义搜索。
在选择如何在 Elasticsearch 中映射嵌入时,重要的是要理解你希望如何生成向量以及对其控制的需求。如果你追求简单性,semantic text 字段可以实现自动且可扩展的语义搜索,非常适合许多初始用例。当需要更多控制、精细的性能调整或与自定义模型集成时,dense vector 和 sparse vector 字段提供了必要的灵活性。
理想的字段类型取决于你的用例、可用基础设施以及机器学习栈的成熟度。最重要的是,Elastic 提供了构建现代且高度适应性搜索系统的工具。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。