Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Přehled
Tato příručka se zabývá hlavními aktualizacemi úložiště vektorů zavedenými v sémantickém jádru verze 1.34, která představuje významnou opravu implementace vektorového úložiště, která odpovídá sadě .NET SDK a poskytuje jednotnější a intuitivnější rozhraní API. Změny konsolidují vše pod semantic_kernel.data.vector a vylepšují architekturu konektoru.
Shrnutí klíčových vylepšení
-
Model sjednoceného pole: Jedna
VectorStoreFieldtřída nahrazuje více typů polí. - Integrované vkládání: Přímé generování vkládání ve specifikacích vektorových polí
- Zjednodušené vyhledávání: Snadné vytváření vyhledávacích funkcí přímo v kolekcích
-
Konsolidovaná struktura: Vše pod
semantic_kernel.data.vectorasemantic_kernel.connectors - Rozšířené vyhledávání textu: Vylepšené možnosti vyhledávání textu se zjednodušenými konektory
-
Vyřazení: Staré
memory_storesjsou odsouzené k vyřazení ve prospěch nové architektury vektorového úložiště.
1. Integrované vkládání a aktualizace modelů a polí úložiště vektorů
Způsob, jakým definujete model vektorového úložiště, existuje celá řada změn. Největší je, že teď podporujeme integrované vkládání přímo do definic polí úložiště vektorů. To znamená, že když zadáte pole, které má být vektorem, obsah tohoto pole se automaticky vloží pomocí zadaného generátoru vkládání, jako je model vkládání textu OpenAI. To zjednodušuje proces vytváření a správy vektorových polí.
Když toto pole definujete, musíte se ujistit o třech věcech, zejména při použití Pydantického modelu:
-
typing: Pole bude pravděpodobně obsahovat tři typy,
list[float],str, nebo něco jiného pro vstup do generátoru vkládání, aNonepro případ, kdy je pole nenastavené. -
výchozí hodnota: Pole musí mít výchozí hodnotu nebo jinou hodnotu
None, takže při získávání záznamů zgetnebosearchsinclude_vectors=Falsevýchozím nastavením neexistuje žádná chyba.
Existují zde dvě problémy, první je, že při dekorování třídy pomocí vectorstoremodel, se první typ anotace pole používá k vyplnění parametru type třídy VectorStoreField, takže je třeba zajistit, aby první typ anotace byl správný typ pro kolekci vektorových úložišť, která má být vytvořena, často list[float]. Ve výchozím nastavení metody get a search nezahrnují None ve výsledcích, takže pole potřebuje výchozí hodnotu a psaní musí tomu odpovídat, proto je často povoleno None a výchozí hodnota je nastavena na None. Při vytváření pole jsou hodnoty, které je potřeba vložit do tohoto pole, často řetězce, takže str je potřeba zahrnout také. Důvodem této změny je umožnit větší flexibilitu v tom, co je vloženo a co je skutečně uloženo v datových polích, toto by bylo běžné nastavení:
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}"
Všimněte si metody post_init, která vytváří hodnotu vloženou do struktury, což přesahuje jeden jediný atribut. Existují také tři typy.
Před: Samostatné třídy polí
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")
]
Po: Unified VectorStoreField s integrovanými vnořeními
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
)
]
Klíčové změny v definici pole
-
Třída s jedním polem:
VectorStoreFieldNahrazuje všechny předchozí typy polí. -
Specifikace typu pole: Použijte
field_type: Literal["key", "data", "vector"]parametr, může to být poziční parametr, takžeVectorStoreField("key")je platný. -
Vylepšené vlastnosti:
-
storage_namebyl přidán, při nastavení se použije jako název pole v úložišti vektorů, jinak se použije parametrname. -
dimensionsje teď povinný parametr pro vektorová pole. -
distance_functionaindex_kindjsou volitelné a budou nastaveny naDistanceFunction.DEFAULTaIndexKind.DEFAULT, pokud nejsou zadány, a to pouze pro vektorová pole. Každá implementace úložiště vektorů má logiku, která zvolí výchozí nastavení pro toto úložiště.
-
-
Přejmenování vlastností:
-
property_typetype_→ jako atribut atypev konstruktorech -
is_filterable→is_indexed -
is_full_text_searchable→is_full_text_indexed
-
-
Integrované vkládání: Přidejte
embedding_generatorpřímo do vektorových polí, případně můžete nastavitembedding_generatorsamotnou kolekci vektorového úložiště, která se použije pro všechna vektorová pole v tomto úložišti, má tato hodnota přednost před generátorem vkládání na úrovni kolekce.
2. Nové metody pro obchody a kolekce
Rozšířené rozhraní úložiště
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.
Rozšířené rozhraní kolekce
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. Rozšířené filtry pro vyhledávání
Nová implementace úložiště vektorů se přesune z objektů FilterClause založených na řetězci na výkonnější a typově bezpečné výrazy lambda nebo volatelné filtry.
Před: FilterClause – objekty
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)
)
Po: Filtry výrazů lambda
# 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
)
Tipy pro migraci pro filtry
-
Jednoduchá rovnost:
filter.equal_to("field", "value")se stáválambda r: r.field == "value" -
Více podmínek: Řetězení s operátory
and/ormísto opakovaného volání filtru -
Zahrnutí značek nebo polí:
filter.any_tag_equal_to("tags", "value")se stanelambda r: "value" in r.tags - Vylepšené možnosti: Podpora dotazů na rozsah, komplexní logickou logiku a vlastní predikáty
4. Vylepšené usnadnění vytváření vyhledávacích funkcí
Před: Vytvoření funkce vyhledávání pomocí 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',
...
)
Po: Vytvoření přímé vyhledávací funkce
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. Přejmenování a import změn konektoru
Sloučení importních cest
# 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
)
Přejmenování třídy konektoru
| Starý název | Nový název |
|---|---|
| AzureCosmosDBforMongoDB* | CosmosMongo* |
| AzureCosmosDBForNoSQL* | CosmosNoSql* |
6. Vylepšení vyhledávání textu a odebrání konektoru Bing
Odebrání konektoru Bingu a rozšířeného rozhraní pro vyhledávání textu
Konektor Bingu pro vyhledávání textu byl odebrán. Migrace na alternativní poskytovatele vyhledávání:
# 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)
Vylepšené metody vyhledávání
Před: Tři samostatné vyhledávací metody s různými návratovými typy
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,
)
After: Sjednocená vyhledávací metoda s parametrem výstupního typu
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. Vyřazení starých úložišť paměti
Všechna stará úložiště paměti založená na MemoryStoreBase byla přesunuta do semantic_kernel.connectors.memory_stores a nyní jsou označena jako zastaralá. Většina z nich má ekvivalentní novou implementaci založenou na VectorStore a VectorStoreCollection, které lze nalézt v semantic_kernel.connectors.memory.
Tyto konektory budou zcela odebrány:
AstraDBMilvusUsearch
Pokud některou z těchto možností přesto potřebujete, nezapomeňte převzít kód z zastaralého semantic_kernel.memory modulu a složky nebo implementovat vlastní kolekci vektorového úložiště založenou na nové VectorStoreCollection třídě.
Pokud na základě zpětné vazby na GitHubu existuje velká poptávka, zvažme jejich vrácení zpět, ale prozatím je neudržujeme a v budoucnu se odeberou.
Migrace z SémanticTextMemory
# 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"
)
Migrace paměťového pluginu
Pokud chcete mít modul plug-in, který může také ukládat informace, můžete snadno vytvořit takto:
# 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")
Kontrolní seznam migrace pro vektorové vyhledávání
Krok 1: Aktualizace importů
- [ ] Nahraďte importy paměťového úložiště ekvivalenty vektorových úložišť
- [ ] Aktualizovat importy polí pro použití
VectorStoreField - [ ] Odstranit importy konektoru Bing
Krok 2: Aktualizace definic polí
- [ ] Převod na sjednocenou
VectorStoreFieldtřídu - [ ] Aktualizovat názvy vlastností (
is_filterable→is_indexed) - [ ] Přidání integrovaných generátorů vkládání do vektorových polí
Krok 3: Aktualizace využití kolekce
- [ ] Nahrazení operací paměti metodami úložiště vektorů
- [ ] Pokud je to možné, použijte nové dávkové operace.
- [ ] Implementace vytvoření nové vyhledávací funkce
Krok 4: Aktualizace implementace vyhledávání
- [ ] Nahrazení ručních vyhledávacích funkcí pomocí
create_search_function - [ ] Aktualizujte vyhledávání textu tak, aby používalo nové zprostředkovatele.
- [ ] Implementace hybridního vyhledávání, kde je výhodné
- [ ] Přechod z
FilterClausevýrazů nalambdavýrazy pro filtrování
Krok 5: Odebrání zastaralého kódu
- [ ] Odebrat
SemanticTextMemorypoužití - [ ] Odebrat
TextMemoryPluginzávislosti
Výhody výkonu a funkcí
Vylepšení výkonu
- Dávkové operace: Nové metody dávkového vložení nebo odstranění zlepšují výkonnost
- Integrované vkládání: Eliminuje samostatné kroky generování vkládání.
- Optimalizované vyhledávání: Předdefinované vyhledávací funkce jsou optimalizované pro každý typ úložiště.
Vylepšení funkcí
- Hybridní vyhledávání: Kombinuje vektorové a textové vyhledávání pro lepší výsledky
- Rozšířené filtrování: Rozšířené výrazy filtru a indexování
Prostředí pro vývojáře
- Zjednodušené rozhraní API: Méně tříd a metod, které se mají naučit
- Konzistentní rozhraní: Jednotný přístup napříč všemi vektorovými úložišti
- Lepší dokumentace: Jasné příklady a migrační cesty
- Připraveno pro budoucnost: V souladu se sadou .NET SDK pro konzistentní multiplatformní vývoj
Závěr
Aktualizace úložiště vektorů, které jsou popsány výše, představují významné vylepšení sady Python SDK sémantického jádra. Nová sjednocená architektura poskytuje lepší výkon, vylepšené funkce a intuitivnější vývojářské prostředí. I když migrace vyžaduje aktualizaci importu a refaktoringu stávajícího kódu, výhody udržovatelnosti a funkčnosti tento upgrade důrazně doporučují.
Další pomoc s migrací najdete v aktualizovaných ukázkách v samples/concepts/memory/ adresáři a v komplexní dokumentaci k rozhraní API.