作者:来自 Elastic Kathleen DeRusso
语义文本搜索现在可以自定义,支持可配置的分块设置和索引选项,用于自定义向量量化,使 semantic_text 在专业用例中更强大。
Elasticsearch 拥有大量新功能,帮助你为你的用例构建最佳搜索解决方案。深入查看我们的示例笔记本以了解更多信息,开始免费云试用,或者立即在本地机器上体验 Elastic。
随着 Elasticsearch 8.18 和 9.0 中 semantic_text 搜索的正式发布,我们的重点主要放在简化使用、提升速度与存储效率,以及扩展可用性以支持 match、 knn 和 sparse_vector 查询。现在,我们要通过为高级和专业用例提供更多自定义功能来完善这个方案。这包括为向量指定要使用的量化方法(包括自定义 BBQ),或者配置可定制的分块设置,以控制 semantic_text 如何将较长的输入拆分为更小的数据片段以传入推理模型。
基于这一目标,我们提供了更多功能,支持对分块设置和量化配置进行更精细的控制。
自定义分块设置
当我们引入 semantic_text 时,其中一个最强大的功能就是它在字段层级上无需额外配置即可自动处理分块。这是因为每个配置好的推理端点(inference endpoint)都附带了分块设置。在使用 semantic_text 摄取文档时,较长的文档会根据该推理端点的配置自动拆分成多个块。
虽然默认的分块配置在大多数用例中表现非常出色,但在某些用例中,需要对分块进行更精细的控制。因此,我们为 semantic_text 引入了可配置的分块设置,当设置后,它将覆盖推理端点中配置的默认行为。
你可以很容易地通过 mapping 来进行设置:
PUT my-index
{
"mappings": {
"properties": {
"my_semantic_field": {
"type": "semantic_text",
"chunking_settings": {
"strategy": "sentence",
"max_chunk_size": 250,
"sentence_overlap": 1
}
}
}
}
}
在这个例子中,我们使用了基于句子的分块策略。它会将数据拆分成包含完整句子的块,每个块的长度不超过 max_chunk_size,在本例中为 250 个词。我们还可以定义 sentence_overlap,它允许同一句子出现在多个块中。此外,我们还支持基于词的分块策略,这种策略会按单词而不是句子边界来拆分数据,或者设置为 none 来完全禁用分块。如果你在将数据发送到 Elasticsearch 之前已经执行了分块,并希望保留这些块不被进一步修改,这种方式就非常有用。关于分块工作原理的更多信息,可以在我们的文档和这篇 search labs 博客中找到。
由于分块设置是在请求时使用的,你可以通过 mapping 更新命令随时修改分块设置:
PUT my-index/_mapping
{
"properties": {
"my_semantic_field": {
"type": "semantic_text",
"chunking_settings": {
"strategy": "word",
"max_chunk_size": 250,
"overlap": 100
}
}
}
}
但请注意,和对 Elasticsearch 中字段 mapping 的其他任何更新一样,这不会影响已索引的文档。如果你决定更改分块配置,并希望所有文档都反映更新后的分块设置,你需要对这些文档重新进行索引。
“自带分块”
另一个我们经常被要求支持的分块配置是:在 semantic_text 字段中完全禁用分块,适用于那些希望在将文档索引到 semantic_text 之前自行执行分块策略的用户。例如,如果你使用基于模型的分块策略来拆分 Markdown 或其他类型的数据。在这种场景下,你会在将内容摄入 Elasticsearch 之前先完成分块操作。
好消息是,现在也支持使用 none 分块策略来实现这一点:
PUT my-index
{
"mappings": {
"properties": {
"my_semantic_field": {
"type": "semantic_text",
"chunking_settings": {
"strategy": "none"
}
}
}
}
}
当使用 none 分块策略时,你可以通过将每个预先分好块的数据单独作为数组中的一个元素发送进来,来显式地索引这些数据块:
PUT my-index/_doc/1
{
"my_semantic_field": [
"These aren't the droids you're looking for",
"He's free to go around"
]
}
提供预先分好块的输入是一种高级用法,并且根据模型的 token 限制来合理设置块的大小非常重要。如果发送的块超出模型的 token 限制,可能会导致错误或文档被截断,具体取决于所使用的服务和模型。
BBQ 和其他量化配置
传统上,semantic_text 一直依赖于适用于文本嵌入模型的良好默认量化策略。这个策略在 8.19 和 9.1 中得到了更新,我们将对所有兼容的文本嵌入模型默认采用最先进的 BBQ HNSW 量化策略来构建使用 semantic_text 的新索引。我们相信这对大多数用例来说是正确的选择,因为实验证明 BBQ 能显著提升文本嵌入模型的表现。
不过我们也理解你可能希望更新这些设置 —— 也许你还没准备好使用 BBQ,或者你想尝试将来一些更优秀的量化改进。放心,我们为你做好了准备!
对于文本嵌入模型( dense vectors ),我们支持使用任意受支持的 dense_vector 配置来设置这些量化索引选项。例如,下面是将一个索引设置为使用 bbq_flat 的方式(它在二进制量化的基础上使用暴力搜索算法,而不是默认的 BBQ 所使用的 HNSW 策略):
PUT my-index
{
"mappings": {
"properties": {
"my_semantic_field": {
"type": "semantic_text",
"inference_id": "my-text-embedding-model",
"index_options": {
"dense_vector": {
"type": "bbq_flat"
}
}
}
}
}
}
这些 index_options 的 mapping 也是可更新的,只要你更新为兼容的量化方法即可。
更多内容即将推出
你可能已经注意到, index_options API 指定的是用于量化的 dense_vector 索引选项。未来,我们还将支持更多索引选项,不仅限于文本嵌入模型,例如 sparse_vector。
立即试用
通过这些令人兴奋的更新,使用 semantic_text 进行的 Elasticsearch 语义搜索既开箱即用,又可根据需要进行高级配置。这些增强功能是 Elasticsearch 的原生能力,将适配未来在分块和量化方面的进一步改进,而且已经在 Serverless 中提供!从 8.19/9.1 版本开始,它们也将在 Stack 托管的 Elasticsearch 中上线。
今天就试试吧!