Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Überblick
In diesem Leitfaden werden die wichtigsten Vektorspeicherupdates behandelt, die in Der Version 1.34 des semantischen Kernels eingeführt wurden. Dies stellt eine erhebliche Überholung der Vektorspeicherimplementierung dar, die sich an das .NET SDK richtet und eine einheitlichere, intuitivere API bereitstellt. Die Änderungen konsolidieren alles unter semantic_kernel.data.vector und verbessern die Konnektorarchitektur.
Zusammenfassung der wichtigsten Verbesserungen
-
Einheitliches Feldmodell: Einzelne
VectorStoreFieldKlasse ersetzt mehrere Feldtypen. - Integrierte Einbettungen: Direkte Einbettungsgenerierung in Vektorfeldspezifikationen
- Vereinfachte Suche: Einfache Erstellung von Suchfunktionen direkt in Sammlungen
-
Konsolidierte Struktur: Alles unter
semantic_kernel.data.vectorundsemantic_kernel.connectors - Erweiterte Textsuche: Verbesserte Textsuchfunktionen mit optimierten Konnektoren
-
Veraltete Funktion: Alte „
memory_stores“ sind zugunsten der neuen Vektorspeicherarchitektur veraltet
1. Integrierte Einbettungen und Vektorspeichermodelle/-felder Updates
Es gibt eine Reihe von Änderungen an der Art und Weise, wie Sie Ihr Vektorspeichermodell definieren, das größte ist, dass wir jetzt integrierte Einbettungen direkt in die Vektorspeicherfelddefinitionen unterstützen. Dies bedeutet, dass der Inhalt dieses Felds automatisch mithilfe des angegebenen Einbettungsgenerators eingebettet wird, z. B. das Texteinbettungsmodell von OpenAI, wenn Sie ein Feld als Vektor angeben. Dies vereinfacht das Erstellen und Verwalten von Vektorfeldern.
Wenn Sie dieses Feld definieren, müssen Sie drei Dinge sicherstellen, insbesondere bei Verwendung eines pydantischen Modells:
-
Tippen: Das Feld könnte drei Typen haben,
list[float],stroder etwas anderes für die Eingabe in den Einbettungsgenerator, undNonefür den Fall, dass das Feld nicht gesetzt ist. -
Standardwert: Das Feld muss einen Standardwert von
Noneoder einen anderen Wert besitzen, damit beim Abrufen von Datensätzen vongetodersearchmitinclude_vectors=False, das jetzt der Standard ist, kein Fehler auftritt.
Es gibt hier zwei Bedenken: Das erste ist, dass beim Dekorieren einer Klasse mit vectorstoremodel die erste Typannotation des Felds verwendet wird, um den type-Parameter der VectorStoreField-Klasse auszufüllen. Daher müssen Sie sicherstellen, dass die erste Typannotation der richtige Typ für die zu erstellende Vektorspeichersammlung ist, oft list[float]. Standardmäßig schließen die Methoden get und search keine Vektoren in die Ergebnisse ein, sodass das Feld einen Standardwert benötigt und die Typisierung damit übereinstimmen muss. Daher ist None häufig zulässig und der Standardwert wird auf None gesetzt. Wenn das Feld erstellt wird, befinden sich die Werte, die eingebettet werden müssen, in diesem Feld, häufig auch Zeichenfolgen, sodass str auch enthalten sein muss. Der Grund für diese Änderung besteht darin, mehr Flexibilität bei dem, was eingebettet wird, und dem, was tatsächlich in Datenfeldern gespeichert ist, zu ermöglichen. Dies wäre eine übliche 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}"
Beachten Sie die post_init-Methode. Dadurch wird ein Wert erstellt, der eingebettet wird und mehr als nur ein einzelnes Feld umfasst. Die drei Typen sind ebenfalls vorhanden.
Vorher: Separate Feldklassen
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")
]
Danach: Vereinheitlichtes VectorStoreField mit integrierten Einbettungen
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
)
]
Wichtige Änderungen in der Felddefinition
-
Single Field Class:
VectorStoreFieldersetzt alle vorherigen Feldtypen -
Feldtypspezifikation: Parameter verwenden
field_type: Literal["key", "data", "vector"], dies kann ein Positionsparameter sein. Dies ist alsoVectorStoreField("key")gültig. -
Erweiterte Eigenschaften:
-
storage_namewurde hinzugefügt, und wenn dieser festgelegt ist, wird er als Feldname im Vektorspeicher verwendet; andernfalls wird dername-Parameter verwendet. -
dimensionsist jetzt ein erforderlicher Parameter für Vektorfelder. -
distance_functionundindex_kindsind beide optional und werden aufDistanceFunction.DEFAULTbzw.IndexKind.DEFAULTfestgelegt, wenn nicht angegeben. Nur für Vektorfelder verfügt jede Vektorspeicherimplementierung über Logik, die einen Standardwert für diesen Speicher auswählt.
-
-
Eigenschaftsumbenennungen:
-
property_typetype_als Attribut undtypein Konstruktoren -
is_filterable→is_indexed -
is_full_text_searchable→is_full_text_indexed
-
-
Integrierte Einbettungen: Fügen Sie
embedding_generatordirekt zu Vektorfeldern hinzu. Alternativ können Sie dieembedding_generatordirekt in der Sammlung im Vektorspeicher festlegen, die für alle Vektorfelder in diesem Speicher verwendet wird. Dieser Wert hat Vorrang vor dem Einbettungsgenerator auf Sammlungsebene.
2. Neue Methoden für Stores und Sammlungen
Erweiterte Store-Schnittstelle
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.
Erweiterte Sammlungsschnittstelle
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. Erweiterte Filter für die Suche
Die neue Implementierung des Vektorspeichers wechselt von Zeichenfolgenbasierten FilterClause-Objekten zu leistungsstärkeren und typsicheren Lambda-Ausdrücken oder aufrufbaren Filtern.
Vor: FilterClause-Objekte
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)
)
Nach: Lambda-Ausdrucksfilter
# 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
)
Migrationstipps für Filter
-
Einfache Gleichheit:
filter.equal_to("field", "value")wirdlambda r: r.field == "value" -
Mehrere Bedingungen: Verketten mit
and/orOperatoren anstelle mehrerer Filteraufrufe -
Tag/Array-Eindämmung:
filter.any_tag_equal_to("tags", "value")wirdlambda r: "value" in r.tags - Erweiterte Funktionen: Unterstützung für Bereichsabfragen, komplexe boolesche Logik und benutzerdefinierte Prädikate
Erleichterte Erstellung von Suchfunktionen
Vorher: Erstellen einer Suchfunktion mit 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',
...
)
Nach: Erstellung einer direkten Suchfunktion
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. Connector benennt Änderungen um und importiert Änderungen
Importpfadkonsolidierung
# 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
)
Umbenennungen der Connector-Klasse
| Alter Name | Neuer Name |
|---|---|
| AzureCosmosDBforMongoDB* | CosmosMongo* |
| AzureCosmosDBForNoSQL* | CosmosNoSql* |
6. Verbesserungen bei der Textsuche und Entfernung des Bing Connectors
Bing Connector entfernt und erweiterte Textsuchschnittstelle
Der Bing-Textsuche-Connector wurde entfernt. Migrieren zu alternativen Suchanbietern:
# 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)
Verbesserte Suchmethoden
Vorher: Drei separate Suchmethoden mit unterschiedlichen Rückgabetypen
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,
)
Nachher: Einheitliche Suchmethode mit Ausgabe-Typ-Parameter
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. Veraltete Speicherorte für alten Speicher
Alle alten Speicher, die auf MemoryStoreBase basieren, wurden in semantic_kernel.connectors.memory_stores verschoben und sind jetzt als veraltet gekennzeichnet. Die meisten von ihnen haben eine gleichwertige neue Implementierung basierend auf VectorStore und VectorStoreCollection, die in „semantic_kernel.connectors.memory“ zu finden ist.
Diese Steckverbinder werden vollständig entfernt.
AstraDBMilvusUsearch
Wenn Sie diese noch benötigen, stellen Sie sicher, dass Sie den Code aus dem veralteten Modul und dem semantic_kernel.memory Ordner übernehmen oder ihre eigene Vektorspeichersammlung basierend auf der neuen VectorStoreCollection Klasse implementieren.
Wenn es eine große Nachfrage auf der Grundlage von GitHub-Feedback gibt, werden wir erwägen, sie zurückzubringen, aber vorerst werden sie nicht gepflegt und in Zukunft entfernt werden.
Migration von 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"
)
Speicher-Plugin-Migration
Wenn Sie über ein Plug-In verfügen möchten, das auch Informationen speichern kann, können Sie das ganz einfach wie folgt erstellen:
# 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")
Migrationsprüfliste für die Vektorsuche
Schritt 1: Aktualisieren von Importen
- [ ] Speicherimporte durch Vektorspeicheräquivalente ersetzen
- Aktualisieren der Feldimporte zur Verwendung
VectorStoreField - [ ] Entfernen von Bing-Connector-Importen
Schritt 2: Aktualisieren von Felddefinitionen
- [ ] In einheitliche
VectorStoreFieldKlasse konvertieren - [ ] Eigenschaftennamen aktualisieren (
is_filterable→is_indexed) - [ ] Integrierte Einbettungsgeneratoren zu Vektorfeldern hinzufügen
Schritt 3: Aktualisieren der Sammlungsverwendung
- [ ] Ersetzen von Speichervorgängen durch Vektorspeichermethoden
- [ ] Verwenden neuer Batchvorgänge, sofern zutreffend
- Implementierung der Erstellung neuer Suchfunktionen
Schritt 4: Aktualisieren der Suchimplementierung
- [ ] Ersetzen manueller Suchfunktionen durch
create_search_function - [ ] Aktualisieren der Textsuche für die Verwendung neuer Anbieter
- [ ] Implementieren der Hybridsuche, wo vorteilhaft
- [ ] Migrieren von
FilterClausezulambdaAusdrücken zum Filtern
Schritt 5: Entfernen veralteter Code
- [ ] Entfernen der Verwendung von
SemanticTextMemory - [ ] Abhängigkeiten
TextMemoryPluginentfernen
Leistungs- und Featurevorteile
Leistungsverbesserungen
- Batchvorgänge: Neue Batch-Upsert-/Löschmethoden verbessern den Durchsatz
- Integrierte Einbettungen: Beseitigt separate Schritte zur Erstellung von Einbettungen
- Optimierte Suche: Integrierte Suchfunktionen sind für jeden Speichertyp optimiert.
Funktionserweiterungen
- Hybridsuche: Kombiniert Vektor- und Textsuche für bessere Ergebnisse
- Erweiterte Filterung: Erweiterte Filterausdrücke und Indizierung
Entwicklererlebnis
- Vereinfachte API: Weniger Klassen und Methoden zum Erlernen
- Einheitliche Schnittstelle: Einheitlicher Ansatz in allen Vektorspeichern
- Bessere Dokumentation: Klare Beispiele und Migrationspfade
- Zukunftssicher: Abgestimmt auf .NET SDK für eine konsistente plattformübergreifende Entwicklung
Schlussfolgerung
Die oben beschriebenen Vektorspeicherupdates stellen eine erhebliche Verbesserung im Semantischer Kernel Python SDK dar. Die neue einheitliche Architektur bietet eine bessere Leistung, verbesserte Features und eine intuitivere Entwicklerumgebung. Die Migration erfordert zwar das Aktualisieren von Importen und umgestalten von vorhandenem Code, aber die Vorteile bei der Wartung und Funktionalität empfehlen dieses Upgrade dringend.
Weitere Hilfe zur Migration finden Sie in den aktualisierten Beispielen im samples/concepts/memory/ Verzeichnis und in der umfassenden API-Dokumentation.