文档
教程
语义搜索

语义搜索

什么是语义搜索?

语义搜索是一种使用 NLP 理解搜索查询的意图和上下文含义的技术。这允许返回与用户意图相关的结果,即使查询不包含确切的关键词。

它是如何工作的?

我们使用诸如 sentence-transformers 之类的文本嵌入模型,将您的文本转换为捕获语义信息的向量。这些向量表示句子的上下文含义。当用户发出搜索查询时,我们将他们的查询编码成向量并搜索类似的文档。

索引文档

我们将依靠 Elasticsearch 来将某些文档字段转换为向量以及将用户的查询转换为向量。

我们将索引 4000 部电影,并对 plot 字段进行向量化。

将嵌入模型加载到 Elasticsearch 中

在这个例子中,我们将使用来自 MiniLM-L6-v2 (在新标签页中打开)sentence-transformers (在新标签页中打开) 库。

按照此 笔记本 (在新标签页中打开) 执行以下步骤。

在笔记本的最后,您将拥有

  1. 在 Elasticsearch 中运行的嵌入模型
  2. 一个索引,它具有一个推理管道,该管道使用嵌入模型将 plot 字段转换为向量
  3. 4000 部电影已摄入索引,并且 plot 字段已转换为向量

创建 Searchkit 应用

我们将克隆 Next.js 示例应用并将其用作起点。

curl https://codeload.github.com/searchkit/searchkit/tar.gz/main | \
tar -xz --strip=2 searchkit-main/examples/with-semantic-search-nextjs

安装依赖项

在项目的根目录中,安装依赖项

yarn

配置 Searchkit

我们将配置 Searchkit 以连接到 Elasticsearch。这取决于 Elasticsearch 的托管方式。在这个例子中,我们使用的是 Elastic Cloud。

app/api/search/route.ts
 
const apiClient = API(
  {
    connection: {
      host: '<elasticsearch-host>',
      apiKey: '<api-key>'
    },
    search_settings: { ... }
  }
)
 

更新显示字段

在这个例子中,我们显示了 titleplot 字段。

app/api/search/route.ts
 
const apiClient = API(
  {
    connection: { ... },
    search_settings: {
      search_attributes: [],
      result_attributes: ['title', 'Plot'],
    }
  }
)
 

以及在 Hits 组件中

app/page.tsx
const HitView = (props: any) => {
  return (
    <div>
      <div className="hit__details">
        <h2>
          {props.hit.title}
        </h2>
        {props.hit.Plot}
      </div>
    </div>
  );
};

配置 Searchkit 查询

现在我们需要更新 Searchkit 的查询以使用执行向量搜索而不是常规搜索。

app/api/search/route.ts
export async function POST(req: NextRequest, res: NextResponse) {
  const data = await req.json()
 
  const results = await apiClient.handleRequest(data, {
    // false to disable keyword search
    getQuery: () => false,
    getKnnQuery: (query) => {
      return {
        field: 'plot_embedding.predicted_value',
        k: 10,
        num_candidates: 50,
        query_vector_builder: {
          text_embedding: {
            model_id: 'sentence-transformers__all-minilm-l6-v2',
            model_text: query
          }
        }
      }
    }
  })
  return NextResponse.json(results)
}

运行应用

yarn dev

混合搜索

在这个例子中,我们使用向量搜索来返回最相关的结果。但是,我们也可以将其与常规关键词搜索结合起来,以返回最相关的匹配查询的结果。

我们首先在 search_settings 配置中定义 search_attributes

app/api/search/route.ts
 
const apiClient = API(
  {
    connection: { ... },
    search_settings: {
      search_attributes: ['title', 'Plot'],
      result_attributes: ['title', 'Plot'],
    }
  }
)
 

然后我们从 handleRequest 调用中删除 getQuery 函数。

在下面的示例中,当客户搜索时,将同时调用默认的 getQuery 和 getKnnQuery。来自两个查询的结果将合并并返回给客户。

我们还将 rrf 参数发送到 Elasticsearch 以平衡来自两个查询的不同分数。

app/api/search/route.ts
export async function POST(req: NextRequest, res: NextResponse) {
  const data = await req.json()
 
  const results = await apiClient.handleRequest(data, {
    getKnnQuery: (query) => {
      return {
        field: 'plot_embedding.predicted_value',
        k: 10,
        num_candidates: 50,
        query_vector_builder: {
          text_embedding: {
            model_id: 'sentence-transformers__all-minilm-l6-v2',
            model_text: query
          }
        }
      }
    }
  })
  return NextResponse.json(results)
}

Apache 2.0 2024 © Joseph McElroy.
需要帮助?加入 Discord