Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Advertencia
La funcionalidad de almacenamiento de vectores del kernel semántico se encuentra en versión RC y las mejoras que requieren modificaciones significativas pueden producirse en circunstancias limitadas antes de su lanzamiento.
Advertencia
La funcionalidad de almacenamiento de vectores del kernel semántico se encuentra en versión preliminar y las mejoras que requieren modificaciones significativas pueden producirse en circunstancias limitadas antes de su lanzamiento.
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 factual o sentido común; repetición o contradicciones; ser sesgado u 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 los dominios o géneros deseados. La base de datos vectorial permite encontrar eficazmente el subconjunto de información relacionada con una pregunta o tema específicos. Después, puede pasar información de la base de datos vectorial con la consulta 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 implementaciones predefinidas que implementan estas abstracciones para varias bases de datos. 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.
Las implementaciones listas para usar se pueden usar con el kernel semántico, pero no dependen de la pila principal del kernel semántico y, por tanto, también se pueden usar por completo de manera independiente si es necesario. El Kernel Semántico proporciona implementaciones que se conocen como "conectores".
Recuperación de generación aumentada (RAG) con almacenes de vectores
La abstracción del almacén de vectores es una API de bajo nivel para agregar y recuperar datos de almacenes vectoriales.
El kernel semántico tiene compatibilidad integrada para usar cualquiera de las implementaciones del almacén de vectores para RAG.
Esto se logra ajustando IVectorSearchable<TRecord> y exponiéndolo como una implementación de Búsqueda de texto.
Sugerencia
Para obtener más información sobre cómo usar almacenes de vectores para RAG, consulte Uso de almacenes de vectores con búsqueda de texto de kernel semántica.
Sugerencia
Para obtener más información sobre la búsqueda de texto, consulte ¿Qué es la búsqueda de texto del kernel semántico?
Sugerencia
Para obtener más información sobre cómo agregar RAG rápidamente al agente, consulte Incorporación de la generación aumentada de recuperación (RAG) a agentes de kernel semántico.
Abstracción del almacén de vectores
Las abstracciones del almacén de vectores se proporcionan en el paquete nuget Microsoft.Extensions.VectorData.Abstractions.
A continuación se muestran las principales interfaces y clases base abstractas.
Microsoft.Extensions.VectorData.VectorStore
VectorStore contiene operaciones que abarcan todas las colecciones del almacén de vectores, por ejemplo, ListCollectionNames.
También proporciona la capacidad de obtener instancias VectorStoreCollection<TKey, TRecord>.
Microsoft.Extensions.VectorData.VectorStoreCollection<TKey, TRecord>
VectorStoreCollection<TKey, TRecord> representa una colección.
Esta colección puede existir o no, y la clase base abstracta proporciona métodos para comprobar si existe la colección, crearla o eliminarla.
La clase base abstracta también proporciona métodos para insertar o actualizar, obtener y eliminar registros.
Por último, la clase base abstracta hereda de IVectorSearchable<TRecord>, lo que proporciona capacidades de búsqueda vectorial.
Microsoft.Extensions.VectorData.IVectorSearchable<TRecord>
SearchAsync<TRecord>se puede usar para hacer lo siguiente:- vectores de búsqueda que utilizan alguna entrada que puede vectorizarse por medio de un generador de incrustaciones registrado o por la base de datos vectorial, si la base de datos lo admite.
- busca vectores tomando un vector como entrada.
Recuperación de generación aumentada (RAG) con almacenes de vectores
Las abstracciones de almacén de vectores son una API de bajo nivel para agregar y recuperar datos de almacenes vectoriales.
El kernel semántico tiene compatibilidad integrada para usar cualquiera de las implementaciones del almacén de vectores para RAG.
Esto se logra ajustando VectorSearchBase[TKey, TModel] con VectorizedSearchMixin[Tmodel], VectorizableTextSearchMixin[TModel] o VectorTextSearch[TModel] y exponiéndolo como una implementación de búsqueda de texto.
Sugerencia
Para obtener más información sobre cómo usar almacenes de vectores para RAG, consulte Uso de almacenes de vectores con búsqueda de texto de kernel semántica.
Sugerencia
Para obtener más información sobre la búsqueda de texto, consulte ¿Qué es la búsqueda de texto del kernel semántico?
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 instancias VectorStoreRecordCollection<Key, Record>.
com.microsoft.semantickernel.data.vectorstorage.VectorStoreRecordCollection<Clave, Registro>
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 actualizar/inserir, obtener y eliminar registros.
Por último, la interfaz hereda de VectorizedSearch<Record> para proporcionar funcionalidades de vectores de búsqueda.
com.microsoft.semantickernel.data.vectorsearch.VectorizedSearch<Registro>
VectorizedSearch<Record> contiene un método para ejecutar vectores de búsqueda.
VectorStoreRecordCollection<Key, Record> hereda de VectorizedSearch<Record> lo que permite el uso de VectorizedSearch<Record> por sí solo en los casos en los que solo se necesita la búsqueda y no se necesita ninguna administración o recopilación de registros.
com.microsoft.semantickernel.data.vectorsearch.VectorizableTextSearch<Registro>
VectorizableTextSearch<Record> contiene un método para ejecutar vectores de búsqueda 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 incrustació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 específicos.
Introducción a los almacenes 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 paquete nuget Microsoft.Extensions.VectorData.Abstractions.
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 forma.
dotnet add package Microsoft.Extensions.VectorData.Abstractions
Definición del modelo de datos
Las abstracciones de Vector Store usan un enfoque basado en 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 las implementaciones de procesos a crear colecciones de registros y mapearlas al esquema de almacenamiento, se puede anotar el modelo para indicar la función de cada propiedad.
using Microsoft.Extensions.VectorData;
public class Hotel
{
[VectorStoreKey]
public ulong HotelId { get; set; }
[VectorStoreData(IsIndexed = true)]
public string HotelName { get; set; }
[VectorStoreData(IsFullTextIndexed = true)]
public string Description { get; set; }
[VectorStoreVector(Dimensions: 4, DistanceFunction = DistanceFunction.CosineSimilarity, IndexKind = IndexKind.Hnsw)]
public ReadOnlyMemory<float>? DescriptionEmbedding { get; set; }
[VectorStoreData(IsIndexed = true)]
public string[] Tags { get; set; }
}
from dataclasses import dataclass, field
from typing import Annotated
from semantic_kernel.data.vector import (
DistanceFunction,
IndexKind,
VectorStoreField,
vectorstoremodel,
)
@vectorstoremodel
@dataclass
class Hotel:
hotel_id: Annotated[str, VectorStoreField('key')] = field(default_factory=lambda: str(uuid4()))
hotel_name: Annotated[str, VectorStoreField('data', is_filterable=True)]
description: Annotated[str, VectorStoreField('data', is_full_text_searchable=True)]
description_embedding: Annotated[list[float], VectorStoreField('vector', dimensions=4, distance_function=DistanceFunction.COSINE, index_kind=IndexKind.HNSW)]
tags: Annotated[list[str], VectorStoreField('data', 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
Si desea ejecutar Qdrant localmente mediante Docker, use el siguiente comando para iniciar el contenedor de Qdrant con la configuración usada en este ejemplo.
docker run -d --name qdrant -p 6333:6333 -p 6334:6334 qdrant/qdrant:latest
Para comprobar que la instancia de Qdrant está en funcionamiento correctamente, visite el panel de Qdrant integrado en el contenedor de Docker de Qdrant: http://localhost:6333/dashboard
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 clase Hotel que ya definimos y el tipo de clave será ulong, ya que la propiedad HotelId es un ulong y 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"), ownsClient: true);
// 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 clase Hotel que ya definimos y el tipo de clave será str, ya que la propiedad HotelId es un str y Qdrant solo admite str o int claves.
from semantic_kernel.connectors.qdrant import QdrantCollection
# Create a collection specify the type of key and record stored in it via Generic parameters.
collection: QdrantCollection[str, Hotel] = QdrantCollection(
record_type=Hotel,
collection_name="skhotels" # this is optional, you can also specify the collection_name in the vectorstoremodel decorator.
)
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 clase Hotel que ya definimos y el tipo de clave será String, ya que la propiedad hotelId es String y Qdrant 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 implementación del almacén de vectores, consulte la documentación de cada implementación.
Creación de la colección y adición de registros
// Placeholder embedding generation method.
async Task<ReadOnlyMemory<float>> GenerateEmbeddingAsync(string textToVectorize)
{
// your logic here
}
// Create the collection if it doesn't exist yet.
await collection.EnsureCollectionExistsAsync();
// 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.
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.ensure_collection_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 inserciones.
Ejecutar un vector de búsqueda
// Placeholder embedding generation method.
async Task<ReadOnlyMemory<float>> GenerateEmbeddingAsync(string textToVectorize)
{
// your logic here
}
// Generate a vector for your search text, using your chosen embedding generation implementation.
ReadOnlyMemory<float> searchVector = await GenerateEmbeddingAsync("I'm looking for a hotel where customer happiness is the priority.");
// Do the search.
var searchResult = collection.SearchAsync(searchVector, top: 1);
// Inspect the returned hotel.
await foreach (var record in searchResult)
{
Console.WriteLine("Found hotel description: " + record.Record.Description);
Console.WriteLine("Found record score: " + record.Score);
}
Ejecutar un vector de búsqueda
El método de búsqueda se puede usar para buscar registros en la colección. Toma una cadena, que luego se vectoriza utilizando la configuración de generación de incrustaciones en el modelo o la colección, o bien un vector que ya ha sido generado.
# Do a search.
search_result = await collection.search("I'm looking for a hotel where customer happiness is the priority.", vector_property_name="description_embedding", top=3)
# Inspect the returned hotels.
async for result in search_result.results:
print(f"Found hotel description: {result.record.description}")
Creación de una función de búsqueda
Para crear una función de búsqueda sencilla que se puede usar para buscar hoteles, puede usar el create_search_function método en la colección.
El nombre y la descripción, así como los nombres y descripciones de los parámetros, se usan para generar una firma de función que se envía al LLM cuando se usa la llamada a función. Esto significa que ajustar esto puede ser útil para hacer que el LLM genere la llamada de función correcta.
collection.create_search_function(
function_name="hotel_search",
description="A hotel search engine, allows searching for hotels in specific cities, "
"you do not have to specify that you are searching for hotels, for all, use `*`."
)
Hay muchos otros parámetros; por ejemplo, esto es lo que parece una versión más compleja, tenga en cuenta la personalización de los parámetros y la string_mapper función que se usa para convertir el registro en una cadena.
from semantic_kernel.function import KernelParameterMetadata
collection.create_search_function(
function_name="hotel_search",
description="A hotel search engine, allows searching for hotels in specific cities, "
"you do not have to specify that you are searching for hotels, for all, use `*`.",
search_type="keyword_hybrid", # default is "vector"
parameters=[
KernelParameterMetadata(
name="query",
description="The terms you want to search for in the hotel database.",
type="str",
is_required=True,
type_object=str,
),
KernelParameterMetadata(
name="tags",
description="The tags you want to search for in the hotel database, use `*` to match all.",
type="str",
type_object=str,
default_value="*",
),
KernelParameterMetadata(
name="top",
description="Number of results to return.",
type="int",
default_value=5,
type_object=int,
),
],
# finally, we specify the `string_mapper` function that is used to convert the record to a string.
# This is used to make sure the relevant information from the record is passed to the LLM.
string_mapper=lambda x: f"Hotel {x.record.hotel_name}: {x.record.description}. Tags: {x.record.tags} (hotel_id: {x.record.hotel_id}) ",
)
Sugerencia
Para obtener más ejemplos, incluidos ejemplos de un extremo a otro, consulte el repositorio De ejemplos de kernel semántico.
// 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 inserciones.