Partilhar via


Pesquisa híbrida no Azure DocumentDB

O Azure DocumentDB suporta agora uma poderosa capacidade de pesquisa híbrida que combina pesquisa vetorial com pontuação de pesquisa em texto completo usando a função Reciprocal Rank Fusion (RRF).

A pesquisa híbrida aproveita os pontos fortes dos métodos de pesquisa baseados em vetores e tradicionais baseados em palavras-chave para fornecer resultados de pesquisa mais relevantes e precisos. Isto é conseguido combinando embeddings vetoriais e dados de texto nos mesmos documentos:

  • Pesquisa vetorial: Utiliza modelos de aprendizado de máquina para entender o significado semântico de consultas e documentos. Isto permite resultados de pesquisa mais conscientes do contexto, especialmente útil para consultas complexas onde a pesquisa tradicional por palavras-chave pode falhar. Para uma pesquisa eficiente por similaridade vetorial, o Azure DocumentDB oferece três cosmosSearchíndices vetoriais compatíveis: HNSW, IVF e DiskANN.
  • Pesquisa em texto completo: O Azure DocumentDB usa $text operador para pesquisa em texto completo.

Os resultados da pesquisa vetorial e da pesquisa em texto integral são então combinados para devolver resultados finais que beneficiam das forças de ambas as abordagens:

  • Relevância Aumentada: Ao combinar compreensão semântica com correspondência de palavras-chave, a pesquisa híbrida pode fornecer resultados mais relevantes para uma vasta gama de consultas.
  • Precisão melhorada: A função RRF garante que os resultados mais pertinentes de ambos os métodos de pesquisa sejam priorizados.
  • Versatilidade: Adequado para vários casos de uso, incluindo sistemas de recomendação, pesquisa semântica e descoberta personalizada de conteúdo.
  1. Crie uma coleção para armazenar os seus dados, incluindo tanto conteúdo de texto como embeddings vetoriais.
  2. Crie um índice vetorial no seu campo de embedding vetorial usando o cosmosSearch operador.
  3. Crie um índice de texto completo no seu campo de texto usando os comandos padrão de criação de índice com o $text tipo.
  4. Use o pipeline de agregação com os operadores $search (para pesquisa vetorial) e $text (para pesquisa em texto completo), seguido de passos para implementar a Fusão de Rank Recíproca para combinar as pontuações usando o operador $unionWith.

Criar um índice de vetores

db.runCommand({
  "createIndexes": "yourCollectionName",
  "indexes": [
    {
      "key": {
        "vectorField": "cosmosSearch"
      },
      "name": "vectorIndex",
      "cosmosSearchOptions": {
        "kind": "vector-diskann", // "vector-ivf" , "vector-hnsw"
        "similarity": "cosine", //  "l2"
        "dimensions": 3072 // Max 16,000
      }
    }
  ]
});

Criar um índice em texto completo

db.runCommand({
  "createIndexes": "yourCollectionName",
  "indexes": [
    {
      "key": {
        "textField": "text"
      },
      "name": "fullTextIndex"
    }
  ]
});
db.hybrid_col.aggregate([
  { $search: { cosmosSearch: { path: "vector", vector: [0.1, 0.2, 0.3], k: 5 } } },  // Vector search
  { $group: { _id: null, vectorResults: { $push: "$$ROOT" } } },
  { $unwind: { path: "$vectorResults", includeArrayIndex: "vectorRank" } },
  { $addFields: { vs_score: { $divide: [1, { $add: ["$vectorRank", 1, 1] }] } } },
  { $project: { _id: "$vectorResults._id", title: "$vectorResults.text", vs_score: 1 } },
  { $unionWith: {
    coll: "hybrid_col",
    pipeline: [
      { $match: { $text: { $search: "cat" } } },
      { $addFields: { textScore: { $meta: "textScore" } } },
      { $group: { _id: null, textResults: { $push: "$$ROOT" } } },
      { $unwind: { path: "$textResults", includeArrayIndex: "textRank" } },
      { $addFields: { fts_score: { $divide: [1, { $add: ["$textRank", 10, 1] }] } } },
      { $project: { _id: "$_id", title: "$text", fts_score: 1 } }
    ]
  }},
  { $group: {
    _id: "$title",
    finalScore: { $max: { $add: [{ $ifNull: ["$vs_score", 0] }, { $ifNull: ["$fts_score", 0] }] } }
  }},
  { $sort: { finalScore: -1 } }
])

Neste exemplo, a primeira $search etapa realiza uma pesquisa de similaridade vetorial no campo vetorial para o vetor [0.1, 0.2, 0.3]de consulta , retornando os cinco documentos mais semelhantes (k: 5). A $group fase agrupa então todos os resultados da pesquisa vetorial num único documento com um array chamado vectorResults. Em seguida, o $unwind estágio desconstrói o vectorResults array, criando um documento separado para cada resultado e adicionando a sua classificação (vectorRank). A etapa seguinte $addFields calcula a pontuação do Reciprocal Rank Fusion (RRF) para cada resultado de pesquisa vetorial com base na sua ordenação. A fase $project seleciona então o _id, o title e o calculado vs_score a partir dos resultados da pesquisa vetorial.

Passando para a fase de pesquisa por texto, a $unionWith etapa combina os resultados do pipeline de pesquisa vetorial com os de um pipeline separado de pesquisa em texto completo. Na fase de pesquisa em texto completo, a etapa $match com o operador $text realiza uma pesquisa em texto completo pelo termo "gato" no campo de texto. O $addFields estágio recupera a pontuação de relevância (textScore) atribuída pelo operador $text. Semelhante aos resultados da pesquisa vetorial, o $group estágio agrupa todos os resultados de pesquisa em texto completo, e o $unwind estágio desconstrói a matriz textResults, adicionando a classificação (textRank). Aqui é usada uma penalização diferente (10), que pode ser ajustada. O $project estágio seleciona os _id, title e fts_score dos resultados de pesquisa em texto completo. Após a combinação dos resultados, o estágio $group agrupa os documentos pelos title.

Finalmente, o $project estágio calcula o finalScore para cada documento tomando o máximo da sua pontuação RRF vetorial (vs_score) e da sua pontuação RRF em texto completo (fts_score). $ifNull trata de casos em que um documento pode estar presente apenas num dos resultados de pesquisa.

Limitações

  • A pesquisa em texto completo do Azure DocumentDB atualmente só suporta a classificação do BM25 em pré-visualização bloqueada.
  • Atualmente, não existe um comando único e dedicado para realizar uma pesquisa híbrida diretamente. É necessário construir a pesquisa híbrida usando o pipeline de agregação, como demonstrado nos exemplos acima.

Próximos passos