Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Översikt
Den här guiden beskriver de viktigaste uppdateringarna av vektorarkivet som introducerades i Semantic Kernel version 1.34, vilket representerar en betydande översyn av implementeringen av vektorarkivet för att anpassa till .NET SDK och tillhandahålla ett mer enhetligt, intuitivt API. Ändringarna konsoliderar allt under semantic_kernel.data.vector och förbättrar anslutningsarkitekturen.
Sammanfattning av viktiga förbättringar
-
Enhetlig fältmodell: En klass
VectorStoreFieldersätter flera fälttyper - Integrerade inbäddningar: Direkt inbäddningsgenerering i specifikationer för vektorfält
- Förenklad sökning: Enkelt att skapa sökfunktioner direkt i samlingar
-
Konsoliderad struktur: Allt under
semantic_kernel.data.vectorochsemantic_kernel.connectors - Förbättrad textsökning: Förbättrade textsökningsmöjligheter med strömlinjeformade kopplingar
-
Utfasning: Gamla
memory_storesär inaktuella till förmån för den nya arkitekturen för vektorlager
1. Integrerade inbäddningar och vektorlagringsmodeller/fältuppdateringar
Det finns ett antal ändringar i hur du definierar vektorlagringsmodellen, det största är att vi nu stöder integrerade inbäddningar direkt i definitionerna för vektorlagerfält. Det innebär att när du anger ett fält som ska vara en vektor bäddas innehållet i fältet automatiskt in med den angivna inbäddningsgeneratorn, till exempel OpenAI:s textinbäddningsmodell. Detta förenklar processen för att skapa och hantera vektorfält.
När du definierar det fältet måste du se till att det finns tre saker, särskilt när du använder en pydantisk modell:
- sv-SE: typning: Fältet kommer sannolikt att ha tre typer,
list[float],streller något annat för indata som ska användas av inbäddningsgeneratorn ochNoneför när fältet inte är konfigurerat. -
standardvärde: Fältet måste ha ett standardvärde på
Noneeller något annat, så att det inte uppstår något fel när poster hämtas frångetellersearchsominclude_vectors=Falseär standard nu.
Det finns två problem här, den första är att när du dekorerar en klass med vectorstoremodelanvänds den första typen av anteckning för fältet för att fylla type parametern i VectorStoreField klassen, så du måste se till att den första typen av anteckning är rätt typ för vektorlagringssamlingen som ska skapas med, ofta list[float]. Som standard inkluderar metoderna get och search inte vektorer i resultaten, så fältet behöver ett standardvärde och datatypen måste motsvara detta; därför tillåts ofta None och standarden sätts till None. När fältet skapas finns de värden som måste bäddas in i det här fältet, ofta strängar, så str måste också inkluderas. Anledningen till den här ändringen är att ge mer flexibilitet i vad som är inbäddat och vad som faktiskt lagras i datafält, detta skulle vara en vanlig konfiguration:
from semantic_kernel.data.vector import VectorStoreField, vectorstoremodel
from typing import Annotated
from dataclasses import dataclass
@vectorstoremodel
@dataclass
class MyRecord:
content: Annotated[str, VectorStoreField('data', is_indexed=True, is_full_text_indexed=True)]
title: Annotated[str, VectorStoreField('data', is_indexed=True, is_full_text_indexed=True)]
id: Annotated[str, VectorStoreField('key')]
vector: Annotated[list[float] | str | None, VectorStoreField(
'vector',
dimensions=1536,
distance_function="cosine",
embedding_generator=OpenAITextEmbedding(ai_model_id="text-embedding-3-small"),
)] = None
def __post_init__(self):
if self.vector is None:
self.vector = f"Title: {self.title}, Content: {self.content}"
Observera post_init metoden, detta skapar ett värde som inbäddas, vilket är mer än ett enda fält. De tre typerna finns också.
Före: Avgränsa fältklasser
from semantic_kernel.data import (
VectorStoreRecordKeyField,
VectorStoreRecordDataField,
VectorStoreRecordVectorField
)
# Old approach with separate field classes
fields = [
VectorStoreRecordKeyField(name="id"),
VectorStoreRecordDataField(name="text", is_filterable=True, is_full_text_searchable=True),
VectorStoreRecordVectorField(name="vector", dimensions=1536, distance_function="cosine")
]
Efter: Unified VectorStoreField med integrerade inbäddningar
from semantic_kernel.data.vector import VectorStoreField
from semantic_kernel.connectors.ai.open_ai import OpenAITextEmbedding
# New unified approach with integrated embeddings
embedding_service = OpenAITextEmbedding(
ai_model_id="text-embedding-3-small"
)
fields = [
VectorStoreField(
"key",
name="id",
),
VectorStoreField(
"data",
name="text",
is_indexed=True, # Previously is_filterable
is_full_text_indexed=True # Previously is_full_text_searchable
),
VectorStoreField(
"vector",
name="vector",
dimensions=1536,
distance_function="cosine",
embedding_generator=embedding_service # Integrated embedding generation
)
]
Viktiga ändringar i fältdefinition
-
Enskild fältklass:
VectorStoreFieldersätter alla tidigare fälttyper -
Fälttypspecifikation: Använd
field_type: Literal["key", "data", "vector"]parameter, det kan vara en positionsparameter, såVectorStoreField("key")den är giltig. -
Förbättrade egenskaper:
-
storage_namehar lagts till, när den anges, som används som fältnamn i vektorlagret, annars används parameternname. -
dimensionsär nu en obligatorisk parameter för vektorfält. -
distance_functionochindex_kindär båda valfria och kommer att anges tillDistanceFunction.DEFAULTrespektiveIndexKind.DEFAULTom de inte anges. Endast för vektorfält har varje implementering av en vektorbutik logik som väljer en standard för den butiken.
-
-
Egenskapsnamnbyten:
-
property_typetype_→ som ett attribut ochtypei konstruktorer -
is_filterable→is_indexed -
is_full_text_searchable→is_full_text_indexed
-
-
Integrerade inbäddningar: Lägg till
embedding_generatordirekt till vektorfält, alternativt kan du angeembedding_generatorpå själva vektorlagringssamlingen, som ska användas för alla vektorfält i det arkivet. Det här värdet har företräde framför inbäddningsgeneratorn på samlingsnivå.
2. Nya metoder för butiker och samlingar
Förbättrat butiksgränssnitt
from semantic_kernel.connectors.in_memory import InMemoryStore
# Before: Limited collection methods
collection = InMemoryStore.get_collection("my_collection", record_type=MyRecord)
# After: Slimmer collection interface with new methods
collection = InMemoryStore.get_collection(MyRecord)
# if the record type has the `vectorstoremodel` decorator it can contain both the collection_name and the definition for the collection.
# New methods for collection management
await store.collection_exists("my_collection")
await store.ensure_collection_deleted("my_collection")
# both of these methods, create a simple model to streamline doing collection management tasks.
# they both call the underlying `VectorStoreCollection` methods, see below.
Förbättrat samlingsgränssnitt
from semantic_kernel.connectors.in_memory import InMemoryCollection
collection = InMemoryCollection(
record_type=MyRecord,
embedding_generator=OpenAITextEmbedding(ai_model_id="text-embedding-3-small") # Optional, if there is no embedding generator set on the record type
)
# If both the collection and the record type have an embedding generator set, the record type's embedding generator will be used for the collection. If neither is set, it is assumed the vector store itself can create embeddings, or that vectors are included in the records already, if that is not the case, it will likely raise.
# Enhanced collection operations
await collection.collection_exists()
await collection.ensure_collection_exists()
await collection.ensure_collection_deleted()
# CRUD methods
# Removed batch operations, all CRUD operations can now take both a single record or a list of records
records = [
MyRecord(id="1", text="First record"),
MyRecord(id="2", text="Second record")
]
ids = ["1", "2"]
# this method adds vectors automatically
await collection.upsert(records)
# You can do get with one or more ids, and it will return a list of records
await collection.get(ids) # Returns a list of records
# you can also do a get without ids, with top, skip and order_by parameters
await collection.get(top=10, skip=0, order_by='id')
# the order_by parameter can be a string or a dict, with the key being the field name and the value being True for ascending or False for descending order.
# At this time, not all vector stores support this method.
# Delete also allows for single or multiple ids
await collection.delete(ids)
query = "search term"
# New search methods, these use the built-in embedding generator to take the value and create a vector
results = await collection.search(query, top=10)
results = await collection.hybrid_search(query, top=10)
# You can also supply a vector directly
query_vector = [0.1, 0.2, 0.3] # Example vector
results = await collection.search(vector=query_vector, top=10)
results = await collection.hybrid_search(query, vector=query_vector, top=10)
3. Förbättrade filter för sökning
Implementeringen av det nya vektorarkivet flyttas från strängbaserade FilterClause-objekt till mer kraftfulla och typsäkra lambda-uttryck eller anropsbara filter.
Före: FilterClause-objekt
from semantic_kernel.data.text_search import SearchFilter, EqualTo, AnyTagsEqualTo
from semantic_kernel.data.vector_search import VectorSearchFilter
# Creating filters using FilterClause objects
text_filter = SearchFilter()
text_filter.equal_to("category", "AI")
text_filter.equal_to("status", "active")
# Vector search filters
vector_filter = VectorSearchFilter()
vector_filter.equal_to("category", "AI")
vector_filter.any_tag_equal_to("tags", "important")
# Using in search
results = await collection.search(
"query text",
options=VectorSearchOptions(filter=vector_filter)
)
Efter: Lambda-uttrycksfilter
# When defining the collection with the generic type hints, most IDE's will be able to infer the type of the record, so you can use the record type directly in the lambda expressions.
collection = InMemoryCollection[str, MyRecord](MyRecord)
# Using lambda expressions for more powerful and type-safe filtering
# The code snippets below work on a data model with more fields then defined earlier.
# Direct lambda expressions
results = await collection.search(
"query text",
filter=lambda record: record.category == "AI" and record.status == "active"
)
# Complex filtering with multiple conditions
results = await collection.search(
"query text",
filter=lambda record: (
record.category == "AI" and
record.score > 0.8 and
"important" in record.tags
)
)
# Combining conditions with boolean operators
results = await collection.search(
"query text",
filter=lambda record: (
record.category == "AI" or record.category == "ML"
) and record.published_date >= datetime(2024, 1, 1)
)
# Range filtering (now possible with lambda expressions)
results = await collection.search(
"query text",
filter=lambda record: 0.5 <= record.confidence_score <= 0.9
)
Migreringstips för filter
-
Enkel likhet:
filter.equal_to("field", "value")blirlambda r: r.field == "value" -
Flera villkor: Kedja med
and/oroperatorer i stället för flera filteranrop -
Tagg/matris-inneslutning:
filter.any_tag_equal_to("tags", "value")blirlambda r: "value" in r.tags - Förbättrade funktioner: Stöd för intervallfrågor, komplex boolesk logik och anpassade predikat
4. Enklare att skapa sökfunktioner
Före: Skapa sökfunktion med VectorStoreTextSearch
from semantic_kernel.connectors.in_memory import InMemoryCollection
from semantic_kernel.data import VectorStoreTextSearch
collection = InMemoryCollection(collection_name='collection', record_type=MyRecord)
search = VectorStoreTextSearch.from_vectorized_search(vectorized_search=collection, embedding_generator=OpenAITextEmbedding(ai_model_id="text-embedding-3-small"))
search_function = search.create_search(
function_name='search',
...
)
Efter: Skapa direktsökningsfunktion
collection = InMemoryCollection(MyRecord)
# Create search function directly on collection
search_function = collection.create_search_function(
function_name="search",
search_type="vector", # or "keyword_hybrid"
top=10,
vector_property_name="vector", # Name of the vector field
)
# Add to kernel directly
kernel.add_function(plugin_name="memory", function=search_function)
5. Byta namn på anslutningar och ändra import
Konsolidering av importsökväg
# Before: Scattered imports
from semantic_kernel.connectors.memory.azure_cognitive_search import AzureCognitiveSearchMemoryStore
from semantic_kernel.connectors.memory.chroma import ChromaMemoryStore
from semantic_kernel.connectors.memory.pinecone import PineconeMemoryStore
from semantic_kernel.connectors.memory.qdrant import QdrantMemoryStore
# After: Consolidated under connectors
from semantic_kernel.connectors.azure_ai_search import AzureAISearchStore
from semantic_kernel.connectors.chroma import ChromaVectorStore
from semantic_kernel.connectors.pinecone import PineconeVectorStore
from semantic_kernel.connectors.qdrant import QdrantVectorStore
# Alternative after: Consolidated with lazy loading:
from semantic_kernel.connectors.memory import (
AzureAISearchStore,
ChromaVectorStore,
PineconeVectorStore,
QdrantVectorStore,
WeaviateVectorStore,
RedisVectorStore
)
Byten av namn på anslutningsklasser
| Gammalt namn | Nytt namn |
|---|---|
| AzureCosmosDBforMongoDB* | CosmosMongo* |
| AzureCosmosDBForNoSQL* | CosmosNoSql* |
6. Förbättringar av textsökning och borttagen Bing-anslutning
Bing-anslutningsprogrammet har tagits bort och textsökningsgränssnittet har förbättrats
Anslutningsappen för textsökning i Bing har tagits bort. Migrera till alternativa sökprovidrar:
# Before: Bing Connector (REMOVED)
from semantic_kernel.connectors.search.bing import BingConnector
bing_search = BingConnector(api_key="your-bing-key")
# After: Use Brave Search or other providers
from semantic_kernel.connectors.brave import BraveSearch
# or
from semantic_kernel.connectors.search import BraveSearch
brave_search = BraveSearch()
# Create text search function
text_search_function = brave_search.create_search_function(
function_name="web_search",
query_parameter_name="query",
description="Search the web for information"
)
kernel.add_function(plugin_name="search", function=text_search_function)
Förbättrade sökmetoder
Före: Tre separata sökmetoder med olika returtyper
from semantic_kernel.connectors.brave import BraveSearch
brave_search = BraveSearch()
# Before: Separate search methods
search_results: KernelSearchResult[str] = await brave_search.search(
query="semantic kernel python",
top=5,
)
search_results: KernelSearchResult[TextSearchResult] = await brave_search.get_text_search_results(
query="semantic kernel python",
top=5,
)
search_results: KernelSearchResult[BraveWebPage] = await brave_search.get_search_results(
query="semantic kernel python",
top=5,
)
Efter: Samlad sökmetod med parameter för utdatatyp
from semantic_kernel.data.text_search import SearchOptions
# Enhanced search results with metadata
search_results: KernelSearchResult[str] = await brave_search.search(
query="semantic kernel python",
output_type=str, # can also be TextSearchResult or anything else for search engine specific results, default is `str`
top=5,
filter=lambda result: result.country == "NL", # Example filter
)
async for result in search_results.results:
assert isinstance(result, str) # or TextSearchResult if using that type
print(f"Result: {result}")
print(f"Metadata: {search_results.metadata}")
7. Utfasning av gamla minneslager
Alla gamla minneslager, baserade på MemoryStoreBase , har flyttats till semantic_kernel.connectors.memory_stores och har nu markerats som inaktuella. De flesta av dem har en motsvarande ny implementering baserad på VectorStore och VectorStoreCollection, som finns i semantic_kernel.connectors.memory.
Dessa kontakter kommer att tas bort helt och hållet.
AstraDBMilvusUsearch
Om du behöver något av dessa fortfarande måste du antingen ta över koden från den inaktuella modulen semantic_kernel.memory och mappen, eller implementera din egen vektorlagringssamling baserat på den nya VectorStoreCollection klassen.
Om det finns en stor efterfrågan baserat på github-feedback överväger vi att ta tillbaka dem, men för tillfället underhålls de inte och tas bort i framtiden.
Migrering från SemanticTextMemory
# Before: SemanticTextMemory (DEPRECATED)
from semantic_kernel.memory import SemanticTextMemory
from semantic_kernel.connectors.ai.open_ai import OpenAITextEmbeddingGenerationService
embedding_service = OpenAITextEmbeddingGenerationService(ai_model_id="text-embedding-3-small")
memory = SemanticTextMemory(storage=vector_store, embeddings_generator=embedding_service)
# Store memory
await memory.save_information(collection="docs", text="Important information", id="doc1")
# Search memory
results = await memory.search(collection="docs", query="important", limit=5)
# After: Direct Vector Store Usage
from semantic_kernel.data.vector import VectorStoreField, vectorstoremodel
from semantic_kernel.connectors.in_memory import InMemoryCollection
# Define data model
@vectorstoremodel
@dataclass
class MemoryRecord:
id: Annotated[str, VectorStoreField('key')]
text: Annotated[str, VectorStoreField('data', is_full_text_indexed=True)]
embedding: Annotated[list[float] | str | None, VectorStoreField('vector', dimensions=1536, distance_function="cosine", embedding_generator=OpenAITextEmbedding(ai_model_id="text-embedding-3-small"))] = None
# Create vector store with integrated embeddings
collection = InMemoryCollection(
record_type=MemoryRecord,
embedding_generator=OpenAITextEmbedding(ai_model_id="text-embedding-3-small") # Optional, if not set on the record type
)
# Store with automatic embedding generation
record = MemoryRecord(id="doc1", text="Important information", embedding='Important information')
await collection.upsert(record)
# Search with built-in function
search_function = collection.create_search_function(
function_name="search_docs",
search_type="vector"
)
Migrering av minnesplugin
När du vill ha ett plugin-program som också kan spara information kan du enkelt skapa det så här:
# Before: TextMemoryPlugin (DEPRECATED)
from semantic_kernel.core_plugins import TextMemoryPlugin
memory_plugin = TextMemoryPlugin(memory)
kernel.add_plugin(memory_plugin, "memory")
# After: Custom plugin using vector store search functions
from semantic_kernel.functions import kernel_function
class VectorMemoryPlugin:
def __init__(self, collection: VectorStoreCollection):
self.collection = collection
@kernel_function(name="save")
async def save_memory(self, text: str, key: str) -> str:
record = MemoryRecord(id=key, text=text, embedding=text)
await self.collection.upsert(record)
return f"Saved to {self.collection.collection_name}"
@kernel_function(name="search")
async def search_memory(self, query: str, limit: int = 5) -> str:
results = await self.collection.search(
query, top=limit, vector_property_name="embedding"
)
return "\n".join([r.record.text async for r in results.results])
# Register the new plugin
memory_plugin = VectorMemoryPlugin(collection)
kernel.add_plugin(memory_plugin, "memory")
Checklista för migrering för vektorsökning
Steg 1: Uppdatera importer
- [ ] Ersätt importer av minneslager med motsvarande vektorlager
- [ ] Uppdatera fältimporter som ska användas
VectorStoreField - [ ] Ta bort importer av Bing-anslutningsprogram
Steg 2: Uppdatera fältdefinitioner
- [ ] Konvertera till enhetlig
VectorStoreFieldklass - [ ] Uppdatera egenskapsnamn (
is_filterable→is_indexed) - [ ] Lägg till integrerade inbäddningsgeneratorer i vektorfält
Steg 3: Uppdatera insamlingsanvändning
- [ ] Ersätt minnesåtgärder med metoder för vektorlagring
- [ ] Använd nya batchåtgärder där det är tillämpligt
- [ ] Implementera skapande av ny sökfunktion
Steg 4: Uppdatera sökimplementeringen
- [ ] Ersätt manuella sökfunktioner med
create_search_function - [ ] Uppdatera textsökning för att använda nya leverantörer
- [ ] Implementera hybridsökning där det är fördelaktigt
- [ ] Migrera från
FilterClausetilllambdauttryck för filtrering
Steg 5: Ta bort inaktuell kod
- [ ] Ta bort
SemanticTextMemoryanvändning - [ ] Ta bort
TextMemoryPluginberoenden
Prestanda- och funktionsfördelar
Prestandaförbättringar
- Batch-åtgärder: Nya batch-upsert/delete-operationer förbättrar genomströmningen
- Integrerade inbäddningar: Eliminerar separata inbäddningsgenereringssteg
- Optimerad sökning: Inbyggda sökfunktioner är optimerade för varje butikstyp
Funktionsförbättringar
- Hybridsökning: Kombinerar vektor- och textsökning för bättre resultat
- Avancerad filtrering: Förbättrade filteruttryck och indexering
Utvecklarupplevelse
- Förenklat API: Färre klasser och metoder att lära sig
- Konsekvent gränssnitt: Enhetlig metod för alla vektorlager
- Bättre dokumentation: Rensa exempel och migreringsvägar
- Framtidssäker: Justerad med .NET SDK för konsekvent plattformsoberoende utveckling
Slutsats
Uppdateringarna av vektorarkivet som beskrivs ovan representerar en betydande förbättring av Semantic Kernel Python SDK. Den nya enhetliga arkitekturen ger bättre prestanda, förbättrade funktioner och en mer intuitiv utvecklarupplevelse. Även om migrering kräver uppdatering av importer och refaktorisering av befintlig kod, rekommenderas uppgraderingen starkt av fördelarna med underhåll och funktioner.
Mer hjälp med migrering finns i de uppdaterade exemplen samples/concepts/memory/ i katalogen och den omfattande API-dokumentationen.