# 语义搜索

Typesense 支持开箱即用的语义搜索功能,既可以使用内置的机器学习模型,也可以使用外部 ML 模型如 OpenAI、PaLM API 和 Vertex AI API(从 v0.25 版本开始支持)。

# 使用场景

语义搜索能够帮助检索与用户查询在概念上相关的结果。

例如,假设用户输入了 "ocean",但您的数据集中只包含关键词 "sea",语义搜索可以帮助找出 "sea" 的结果,因为 "ocean" 与 "sea" 是相关联的。

本文将使用一个简单的产品数据集,向您展示如何通过几个步骤实现语义搜索。

# 第一步:创建集合

这与创建常规集合非常相似,只是需要添加下面高亮的 自动嵌入字段

在本示例中,我们使用内置的 ML 模型 ts/all-MiniLM-L12-v2(即 S-BERT)来自动从我们将添加到该集合的文档中的 product_name 字段生成嵌入向量。

你也可以使用 OpenAIPaLM APIVertex AI API,让 Typesense 自动调用这些服务的 API 来生成支持语义搜索的嵌入向量。

你也可以通过指定 ts/<模型名称> 来使用我们 HuggingFace 仓库 (opens new window) 中的任何内置 ML 模型。

# 第二步:索引你的 JSON 数据

你可以像往常一样将 JSON 数据发送到 Typesense:

curl "http://localhost:8108/collections/products/documents/import?action=create" \
        -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
        -H "Content-Type: text/plain" \
        -X POST \
        -d '{"product_name": "Cell phone"}
            {"product_name": "Laptop"}
            {"product_name": "Desktop"}
            {"product_name": "Printer"}
            {"product_name": "Keyboard"}
            {"product_name": "Monitor"}
            {"product_name": "Mouse"}'

Typesense 会自动使用你在创建 schema 时指定的 ML 模型,为每个 JSON 文档生成并存储嵌入向量。

就是这样!现在可以进行语义搜索了。

# 第三步:语义搜索

要进行语义搜索,我们只需要在 query_by 搜索参数中添加 embedding 字段:







 
 








curl 'http://localhost:8108/multi_search' \
    -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
    -X POST \
    -d '{
      "searches": [
        {
          "q": "device to type things on",
          "query_by": "embedding",
          "collection": "products",
          "prefix": "false",
          "exclude_fields": "embedding",
          "per_page": 1
        }
      ]
    }'

这将返回以下结果。

请注意,我们搜索的是 device to type things on(用来打字的设备),尽管这些关键词在我们的 JSON 数据集中并不存在,Typesense 仍然能够进行语义搜索并返回 Keyboard(键盘)作为结果,因为它们在概念上是相关的:










 



















{
  "results": [
    {
      "facet_counts": [],
      "found": 1,
      "hits": [
        {
          "document": {
            "id": "4",
            "product_name": "Keyboard"
          },
          "highlight": {},
          "highlights": [],
          "vector_distance": 0.38377559185028076
        }
      ],
      "out_of": 7,
      "page": 1,
      "request_params": {
        "collection_name": "products",
        "per_page": 1,
        "q": "device to type things on"
      },
      "search_cutoff": false,
      "search_time_ms": 16
    }
  ]
}

在许多场景中,您可能希望将关键词搜索与语义搜索结合使用。我们称之为混合搜索。

在 Typesense 中,您可以通过在 query_by 参数中同时指定关键词字段和自动嵌入字段来实现这一点:







 
 








curl 'http://localhost:8108/multi_search' \
    -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
    -X POST \
    -d '{
      "searches": [
        {
          "query_by": "product_name,embedding",
          "q": "desktop copier",
          "collection": "products",
          "prefix": "false",
          "exclude_fields": "embedding",
          "per_page": 2
        }
      ]
    }'

这将返回以下结果。

请注意,搜索 Desktop copier 时首先返回了关键词匹配的结果 Desktop,其次是语义匹配的结果 Printer










 


































 






























{
  "results": [
    {
      "facet_counts": [],
      "found": 7,
      "hits": [
        {
          "document": {
            "id": "2",
            "product_name": "Desktop"
          },
          "highlight": {
            "product_name": {
              "matched_tokens": [
                "Desktop"
              ],
              "snippet": "<mark>Desktop</mark>"
            }
          },
          "highlights": [
            {
              "field": "product_name",
              "matched_tokens": [
                "Desktop"
              ],
              "snippet": "<mark>Desktop</mark>"
            }
          ],
          "hybrid_search_info": {
            "rank_fusion_score": 0.8500000238418579
          },
          "text_match": 1060320051,
          "text_match_info": {
            "best_field_score": "517734",
            "best_field_weight": 102,
            "fields_matched": 3,
            "score": "1060320051",
            "tokens_matched": 0
          },
          "vector_distance": 0.510231614112854
        },
        {
          "document": {
            "id": "3",
            "product_name": "Printer"
          },
          "highlight": {},
          "highlights": [],
          "hybrid_search_info": {
            "rank_fusion_score": 0.30000001192092896
          },
          "text_match": 0,
          "text_match_info": {
            "best_field_score": "0",
            "best_field_weight": 0,
            "fields_matched": 0,
            "score": "0",
            "tokens_matched": 0
          },
          "vector_distance": 0.4459354281425476
        }
      ],
      "out_of": 7,
      "page": 1,
      "request_params": {
        "collection_name": "products",
        "per_page": 2,
        "q": "desktop copier"
      },
      "search_cutoff": false,
      "search_time_ms": 22
    }
  ]
}

# 混合匹配结果的重排序

在进行混合搜索时,Typesense 默认会在结果中同时返回关键词匹配和语义匹配。例如:

curl 'http://localhost:8108/multi_search' \
    -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
    -X POST \
    -d '{
      "searches": [
        {
          "query_by": "product_name,embedding",
          "q": "desktop copier",
          "collection": "products",
          "prefix": "false",
          "exclude_fields": "embedding",
          "per_page": 2
        }
      ]
    }'

搜索 "desktop copier" 可能会返回如下结果:


















 



 









 



 



{
  "hits": [
    {
      "document": {
        "id": "2",
        "product_name": "Desktop"
      },
      "highlight": {
        "product_name": {
          "matched_tokens": ["Desktop"],
          "snippet": "<mark>Desktop</mark>"
        }
      },
      "hybrid_search_info": {
        "rank_fusion_score": 0.8500000238418579
      },
      "text_match": 1060320051,
      "text_match_info": {
        "best_field_score": "517734"
      },
      "vector_distance": 0.510231614112854
    },
    {
      "document": {
        "id": "3",
        "product_name": "Printer"
      },
      "hybrid_search_info": {
        "rank_fusion_score": 0.30000001192092896
      },
      "text_match": 0,
      "text_match_info": {
        "best_field_score": "0"
      },
      "vector_distance": 0.4459354281425476
    }
  ]
}

请注意:

  • 第一个结果 "Desktop" 是关键词匹配(text_match 分数高)
  • 第二个结果 "Printer" 是语义匹配(vector_distance 低但 text_match 为零)

默认情况下:

  • 通过关键词搜索但未通过向量搜索找到的文档只会具有文本匹配分数
  • 通过向量搜索但未通过关键词搜索找到的文档只会具有向量距离分数

您可以选择通过设置 rerank_hybrid_matches: true 为所有匹配计算两种分数。启用后:

  • 仅通过关键词搜索找到的文档也会获得向量距离分数
  • 仅通过向量搜索找到的文档也会获得文本匹配分数

启用重排序的示例:










 






curl 'http://localhost:8108/multi_search' \
    -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
    -X POST \
    -d '{
          "searches": [
            {
              "collection": "products",
              "query_by": "embedding,product_name", 
              "q": "desktop copier",
              "rerank_hybrid_matches": true,
              "vector_query": "embedding:([], alpha: 0.8)",
              "exclude_fields": "embedding"
            }
          ]
        }'

这会通过为所有匹配计算两种分数来提供更全面的结果排序,但需要额外的计算时间。

# 分页

要实现语义搜索或混合搜索的有效分页,可以在 vector_search 中使用 k 参数将搜索范围限定在特定数量的最近邻项:











 

 
 




curl 'http://localhost:8108/multi_search' \
  -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
  -X POST \
  -d '{
    "searches": [
      {
        "q": "device to type things on",
        "query_by": "embedding",
        "collection": "products",
        "prefix": "false",
        "vector_query": "embedding:([], k: 200)",
        "exclude_fields": "embedding",
        "per_page": 10,
        "page": 1
      }
    ]
  }'
  • vector_query 参数设置为 embedding:([], k: 200),将向量搜索限制在最近的 200 个相邻项内。
  • per_page 设置为 10,返回按相关性排序的前 10 个结果。
  • 然后可以使用 page 参数对结果进行分页浏览。

可选地,你可以在 vector_query 中使用 distance_threshold 参数来微调语义搜索结果:











 





curl 'http://localhost:8108/multi_search' \
  -H "X-TYPESENSE-API-KEY: ${TYPESENSE_API_KEY}" \
  -X POST \
  -d '{
    "searches": [
      {
        "q": "device to type things on",
        "query_by": "embedding",
        "collection": "products",
        "prefix": "false",
        "vector_query": "embedding:([], k: 200, distance_threshold: 1.0)",
        "exclude_fields": "embedding",
      }
    ]
  }'

有关 vector_query 参数及其选项的更多详情,请参阅向量搜索的 API 文档

# 实时演示

这里有一个在线演示 (opens new window),展示了如何实现语义搜索(Semantic Search)和混合搜索(Hybrid Search)。

你可以在描述中找到相关的源代码链接。

完整的 API 参考文档请阅读 向量搜索(Vector Search)

注意:CPU 使用率

内置的机器学习模型对计算资源要求较高。

因此根据数据集大小的不同,当你启用语义搜索并使用内置 ML 模型时,即使是几千条记录也可能需要花费数十分钟来生成嵌入向量并建立索引。

如果想加速这个过程,你需要在 Typesense 中启用 GPU 加速

当你在 Typesense 中使用像 OpenAI 这样的远程嵌入服务时,则不需要 GPU,因为模型运行在 OpenAI 的服务器上。