Compartir a través de


¿Qué son los conectores del almacén de vectores de kernel semántico? (Versión preliminar)

Advertencia

La funcionalidad Almacén de vectores de kernel semántico está en versión preliminar y las mejoras que requieren cambios importantes pueden producirse en circunstancias limitadas antes de la versión.

Sugerencia

Si busca información sobre los conectores heredados del almacén de memoria, consulte la página Almacenes de memoria.

Las bases de datos vectoriales tienen muchos casos de uso en distintos dominios y aplicaciones que implican el procesamiento de lenguaje natural (NLP), computer vision (CV), sistemas de recomendación (RS) y otras áreas que requieren comprensión semántica y coincidencia de datos.

Un caso de uso para almacenar información en una base de datos vectorial es permitir que los modelos de lenguaje grandes (LLM) generen respuestas más relevantes y coherentes. Los modelos de lenguaje de gran tamaño suelen enfrentar desafíos como generar información inexacta o irrelevante; falta de coherencia fáctica o sentido común; repetir o contradecirse; ser sesgado o ofensivo. Para ayudar a superar estos desafíos, puede usar una base de datos vectorial para almacenar información sobre diferentes temas, palabras clave, hechos, opiniones o orígenes relacionados con su dominio o género deseados. La base de datos vectorial permite encontrar eficazmente el subconjunto de información relacionada con una pregunta o tema específicos. A continuación, puede pasar información de la base de datos vectorial con el mensaje al modelo de lenguaje grande para generar contenido más preciso y relevante.

Por ejemplo, si desea escribir una entrada de blog sobre las tendencias más recientes en ia, puede usar una base de datos vectorial para almacenar la información más reciente sobre ese tema y pasar la información junto con la solicitud a un LLM para generar una entrada de blog que aproveche la información más reciente.

El kernel semántico y .net proporcionan una abstracción para interactuar con los almacenes de vectores y una lista de conectores predefinidos que implementan estas abstracciones. Las características incluyen crear, enumerar y eliminar colecciones de registros y cargar, recuperar y eliminar registros. La abstracción facilita el experimento con un almacén de vectores hospedado local o gratuito y, a continuación, cambiar a un servicio cuando necesite escalar verticalmente.

Abstracción del almacén de vectores

Las interfaces principales de la abstracción del almacén de vectores son las siguientes.

Microsoft.Extensions.VectorData.IVectorStore

IVectorStore contiene operaciones que abarcan todas las colecciones del almacén de vectores, por ejemplo, ListCollectionNames. También proporciona la capacidad de obtener IVectorStoreRecordCollection<TKey, TRecord> instancias.

Microsoft.Extensions.VectorData.IVectorStoreRecordCollection<TKey, TRecord>

IVectorStoreRecordCollection<TKey, TRecord> representa una colección. Esta colección puede existir o no, y la interfaz proporciona métodos para comprobar si la colección existe, crearla o eliminarla. La interfaz también proporciona métodos para upsert, get y delete records. Por último, la interfaz hereda de proporcionar funcionalidades de IVectorizedSearch<TRecord> búsqueda vectorial.

Microsoft.Extensions.VectorData.IVectorizedSearch<TRecord>

IVectorizedSearch<TRecord> contiene un método para realizar búsquedas vectoriales. IVectorStoreRecordCollection<TKey, TRecord> hereda de IVectorizedSearch<TRecord> permitir su uso IVectorizedSearch<TRecord> por sí solo en los casos en los que solo se necesita la búsqueda y no se necesita ninguna administración de registros o recopilación.

IVectorizableTextSearch<TRecord>

IVectorizableTextSearch<TRecord> contiene un método para realizar búsquedas vectoriales en las que la base de datos vectorial tiene la capacidad de generar incrustaciones automáticamente. Por ejemplo, puede llamar a este método con una cadena de texto y la base de datos generará la inserción automáticamente y buscará en un campo vectorial. Esto no es compatible con todas las bases de datos vectoriales y, por tanto, solo se implementa mediante conectores seleccionados.

Abstracción del almacén de vectores

Las interfaces principales de la abstracción del almacén de vectores son las siguientes.

com.microsoft.semantickernel.data.vectorstorage.VectorStore

VectorStore contiene operaciones que abarcan todas las colecciones del almacén de vectores, por ejemplo, listCollectionNames. También proporciona la capacidad de obtener VectorStoreRecordCollection<Key, Record> instancias.

com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection<Key, Record>

VectorStoreRecordCollection<Key, Record> representa una colección. Esta colección puede existir o no, y la interfaz proporciona métodos para comprobar si la colección existe, crearla o eliminarla. La interfaz también proporciona métodos para upsert, get y delete records. Por último, la interfaz hereda de proporcionar funcionalidades de VectorizedSearch<Record> búsqueda vectorial.

Registro com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<>

VectorizedSearch<Record> contiene un método para realizar búsquedas vectoriales. VectorStoreRecordCollection<Key, Record> hereda de VectorizedSearch<Record> permitir su uso VectorizedSearch<Record> por sí solo en los casos en los que solo se necesita la búsqueda y no se necesita ninguna administración de registros o recopilación.

Registro com.microsoft.semantickernel.data.vectorsearch.VectorizableTextSearch<>

VectorizableTextSearch<Record> contiene un método para realizar búsquedas vectoriales en las que la base de datos vectorial tiene la capacidad de generar incrustaciones automáticamente. Por ejemplo, puede llamar a este método con una cadena de texto y la base de datos generará la inserción automáticamente y buscará en un campo vectorial. Esto no es compatible con todas las bases de datos vectoriales y, por tanto, solo se implementa mediante conectores seleccionados.

Introducción a los conectores del almacén de vectores

Importación de los paquetes nuget necesarios

Todas las interfaces de almacén de vectores y las clases relacionadas con abstracción están disponibles en el Microsoft.Extensions.VectorData.Abstractions paquete nuget. Cada implementación del almacén de vectores está disponible en su propio paquete nuget. Para obtener una lista de implementaciones conocidas, consulte la página Conectores predefinidos.

El paquete de abstracciones se puede agregar de esta manera.

dotnet add package Microsoft.Extensions.VectorData.Abstractions --prerelease

Advertencia

A partir de la versión 1.23.0 del kernel semántico, las abstracciones del almacén de vectores se han quitado Microsoft.SemanticKernel.Abstractions de y están disponibles en el nuevo paquete dedicado Microsoft.Extensions.VectorData.Abstractions .

Tenga en cuenta que, a partir de la versión 1.23.0, Microsoft.SemanticKernel.Abstractions tiene una dependencia de Microsoft.Extensions.VectorData.Abstractions, por lo tanto, no es necesario hacer referencia a paquetes adicionales. Sin embargo, las abstracciones estarán ahora en el nuevo Microsoft.Extensions.VectorData espacio de nombres.

Al actualizar de la versión 1.22.0 o anterior a 1.23.0 o posterior, deberá agregar una cláusula adicional using Microsoft.Extensions.VectorData; en los archivos en los que se use cualquiera de los tipos de abstracción del almacén de vectores, por ejemplo IVectorStore, , IVectorStoreRecordCollection, VectorStoreRecordDataAttribute, VectorStoreRecordKeyPropertyetc.

Este cambio se ha realizado para admitir proveedores de almacén de vectores al crear sus propias implementaciones. Un proveedor solo tiene que hacer referencia al Microsoft.Extensions.VectorData.Abstractions paquete. Esto reduce los posibles conflictos de versiones y permite que el kernel semántico continúe evolucionando rápidamente sin afectar a los proveedores de almacén de vectores.

Definición del modelo de datos

Los conectores de almacén de vectores de kernel semántico usan un primer enfoque de modelo para interactuar con las bases de datos. Esto significa que el primer paso es definir un modelo de datos que se asigna al esquema de almacenamiento. Para ayudar a los conectores a crear colecciones de registros y asignarse al esquema de almacenamiento, el modelo se puede anotar para indicar la función de cada propiedad.

using Microsoft.Extensions.VectorData;

public class Hotel
{
    [VectorStoreRecordKey]
    public ulong HotelId { get; set; }

    [VectorStoreRecordData(IsFilterable = true)]
    public string HotelName { get; set; }

    [VectorStoreRecordData(IsFullTextSearchable = true)]
    public string Description { get; set; }

    [VectorStoreRecordVector(Dimensions: 4, DistanceFunction.CosineDistance, IndexKind.Hnsw)]
    public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }

    [VectorStoreRecordData(IsFilterable = true)]
    public string[] Tags { get; set; }
}
from dataclasses import dataclass, field
from typing import Annotated
from semantic_kernel.data import (
    DistanceFunction,
    IndexKind,
    VectorStoreRecordDataField,
    VectorStoreRecordDefinition,
    VectorStoreRecordKeyField,
    VectorStoreRecordVectorField,
    vectorstoremodel,
)

@vectorstoremodel
@dataclass
class Hotel:
    hotel_id: Annotated[str, VectorStoreRecordKeyField()] = field(default_factory=lambda: str(uuid4()))
    hotel_name: Annotated[str, VectorStoreRecordDataField(is_filterable=True)]
    description: Annotated[str, VectorStoreRecordDataField(is_full_text_searchable=True)]
    description_embedding: Annotated[list[float], VectorStoreRecordVectorField(dimensions=4, distance_function=DistanceFunction.COSINE, index_kind=IndexKind.HNSW)]
    tags: Annotated[list[str], VectorStoreRecordDataField(is_filterable=True)]
import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordData;
import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordKey;
import com.microsoft.semantickernel.data.vectorstorage.annotations.VectorStoreRecordVector;
import com.microsoft.semantickernel.data.vectorstorage.definition.DistanceFunction;
import com.microsoft.semantickernel.data.vectorstorage.definition.IndexKind;

import java.util.Collections;
import java.util.List;

public class Hotel {
    @VectorStoreRecordKey
    private String hotelId;

    @VectorStoreRecordData(isFilterable = true)
    private String name;

    @VectorStoreRecordData(isFullTextSearchable = true)
    private String description;

    @VectorStoreRecordVector(dimensions = 4, indexKind = IndexKind.HNSW, distanceFunction = DistanceFunction.COSINE_DISTANCE)
    private List<Float> descriptionEmbedding;

    @VectorStoreRecordData(isFilterable = true)
    private List<String> tags;

    public Hotel() { }

    public Hotel(String hotelId, String name, String description, List<Float> descriptionEmbedding, List<String> tags) {
        this.hotelId = hotelId;
        this.name = name;
        this.description = description;
        this.descriptionEmbedding = Collections.unmodifiableList(descriptionEmbedding);
        this.tags = Collections.unmodifiableList(tags);
    }

    public String getHotelId() { return hotelId; }
    public String getName() { return name; }
    public String getDescription() { return description; }
    public List<Float> getDescriptionEmbedding() { return descriptionEmbedding; }
    public List<String> getTags() { return tags; }
}

Sugerencia

Para obtener más información sobre cómo anotar el modelo de datos, consulte definición del modelo de datos.

Sugerencia

Para obtener una alternativa a anotar el modelo de datos, consulte definición del esquema con una definición de registro.

Conexión a la base de datos y selección de una colección

Una vez que haya definido el modelo de datos, el siguiente paso es crear una instancia de VectorStore para la base de datos de su elección y seleccionar una colección de registros.

En este ejemplo, usaremos Qdrant. Por lo tanto, deberá importar el paquete nuget Qdrant.

dotnet add package Microsoft.SemanticKernel.Connectors.Qdrant --prerelease

Dado que las bases de datos admiten muchos tipos diferentes de claves y registros, le permitimos especificar el tipo de clave y registro de la colección mediante genéricos. En nuestro caso, el tipo de registro será la Hotel clase que ya definimos y el tipo de clave será ulong, ya que la HotelId propiedad es y ulong Qdrant solo admite Guid o ulong claves.

using Microsoft.SemanticKernel.Connectors.Qdrant;
using Qdrant.Client;

// Create a Qdrant VectorStore object
var vectorStore = new QdrantVectorStore(new QdrantClient("localhost"));

// Choose a collection from the database and specify the type of key and record stored in it via Generic parameters.
var collection = vectorStore.GetCollection<ulong, Hotel>("skhotels");

Dado que las bases de datos admiten muchos tipos diferentes de claves y registros, le permitimos especificar el tipo de clave y registro de la colección mediante genéricos. En nuestro caso, el tipo de registro será la Hotel clase que ya definimos y el tipo de clave será str, ya que la HotelId propiedad es y str Qdrant solo admite str o int claves.

from semantic_kernel.connectors.memory.qdrant import QdrantStore

# Create a Qdrant VectorStore object, this will look in the environment for Qdrant related settings, and will fall back to the default, which is to run in-memory.
vector_store = QdrantStore()

# Choose a collection from the database and specify the type of key and record stored in it via Generic parameters.
collection = vector_store.get_collection(
    collection_name="skhotels", 
    data_model_type=Hotel
)

Dado que las bases de datos admiten muchos tipos diferentes de claves y registros, le permitimos especificar el tipo de clave y registro de la colección mediante genéricos. En nuestro caso, el tipo de registro será la Hotel clase que ya definimos y el tipo de clave será String, ya que la hotelId propiedad es un String almacén JDBC y solo admite String claves.

import com.microsoft.semantickernel.data.jdbc.JDBCVectorStore;
import com.microsoft.semantickernel.data.jdbc.JDBCVectorStoreOptions;
import com.microsoft.semantickernel.data.jdbc.JDBCVectorStoreRecordCollectionOptions;
import com.microsoft.semantickernel.data.jdbc.mysql.MySQLVectorStoreQueryProvider;
import com.mysql.cj.jdbc.MysqlDataSource;

import java.util.List;

public class Main {
    public static void main(String[] args) {
        // Create a MySQL data source
        var dataSource = new MysqlDataSource();
        dataSource.setUrl("jdbc:mysql://localhost:3306/sk");
        dataSource.setPassword("root");
        dataSource.setUser("root");

        // Create a JDBC vector store
        var vectorStore = JDBCVectorStore.builder()
            .withDataSource(dataSource)
            .withOptions(
                JDBCVectorStoreOptions.builder()
                    .withQueryProvider(MySQLVectorStoreQueryProvider.builder()
                        .withDataSource(dataSource)
                        .build())
                    .build()
            )
            .build();

        // Get a collection from the vector store
        var collection = vectorStore.getCollection("skhotels",
            JDBCVectorStoreRecordCollectionOptions.<Hotel>builder()
                .withRecordClass(Hotel.class)
                .build()
        );
    }
}

Sugerencia

Para obtener más información sobre qué tipos de clave y campo admite cada conector de almacén de vectores, consulte la documentación de cada conector.

Creación de la colección y adición de registros

// Create the collection if it doesn't exist yet.
await collection.CreateCollectionIfNotExistsAsync();

// Upsert a record.
string descriptionText = "A place where everyone can be happy.";
ulong hotelId = 1;

// Create a record and generate a vector for the description using your chosen embedding generation implementation.
// Just showing a placeholder embedding generation method here for brevity.
await collection.UpsertAsync(new Hotel
{
    HotelId = hotelId,
    HotelName = "Hotel Happy",
    Description = descriptionText,
    DescriptionEmbedding = await GenerateEmbeddingAsync(descriptionText),
    Tags = new[] { "luxury", "pool" }
});

// Retrieve the upserted record.
Hotel? retrievedHotel = await collection.GetAsync(hotelId);

Creación de la colección y adición de registros

# Create the collection if it doesn't exist yet.
await collection.create_collection_if_not_exists()

# Upsert a record.
description = "A place where everyone can be happy."
hotel_id = "1"

await collection.upsert(Hotel(
    hotel_id = hotel_id,
    hotel_name = "Hotel Happy",
    description = description,
    description_embedding = await GenerateEmbeddingAsync(description),
    tags = ["luxury", "pool"]
))

# Retrieve the upserted record.
retrieved_hotel = await collection.get(hotel_id)
// Create the collection if it doesn't exist yet.
collection.createCollectionAsync().block();

// Upsert a record.
var description = "A place where everyone can be happy";
var hotelId = "1";
var hotel = new Hotel(
    hotelId, 
    "Hotel Happy", 
    description, 
    generateEmbeddingsAsync(description).block(), 
    List.of("luxury", "pool")
);

collection.upsertAsync(hotel, null).block();

// Retrieve the upserted record.
var retrievedHotel = collection.getAsync(hotelId, null).block();

Sugerencia

Para obtener más información sobre cómo generar incrustaciones, consulte Generación de inserción.

// Generate a vector for your search text, using your chosen embedding generation implementation.
// Just showing a placeholder method here for brevity.
var searchVector = await GenerateEmbeddingAsync("I'm looking for a hotel where customer happiness is the priority.");
// Do the search.
var searchResult = await collection.VectorizedSearchAsync(searchVector, new() { Top = 1 }).Results.ToListAsync()

// Inspect the returned hotels.
Hotel hotel = searchResult.First().Record;
Console.WriteLine("Found hotel description: " + hotel.Description);
// Generate a vector for your search text, using your chosen embedding generation implementation.
// Just showing a placeholder method here for brevity.
var searchVector = generateEmbeddingsAsync("I'm looking for a hotel where customer happiness is the priority.").block();

// Do the search.
var searchResult = collection.searchAsync(searchVector, VectorSearchOptions.builder()
    .withTop(1).build()
).block();

Hotel record = searchResult.getResults().get(0).getRecord();
System.out.printf("Found hotel description: %s\n", record.getDescription());

Sugerencia

Para obtener más información sobre cómo generar incrustaciones, consulte Generación de inserción.

Pasos siguientes