Semantik Çekirdek Python Vektör Deposu Geçiş Kılavuzu

Genel Bakış

Bu kılavuz, .NET SDK'sı ile uyumlu ve daha birleşik, sezgisel bir API sağlamak için vektör deposu uygulamasının önemli ölçüde elden geçirilmesini temsil eden Anlam Çekirdeği sürüm 1.34'te sunulan ana vektör deposu güncelleştirmelerini kapsar. Değişiklikler, her şeyi semantic_kernel.data.vector altında toplar ve bağlayıcı mimarisini geliştirir.

Önemli Geliştirmeler Özeti

  • Birleşik Alan Modeli: Tek VectorStoreField sınıf birden çok alan türünün yerini alır
  • Tümleşik Eklemeler: Vektör alanı belirtimlerine doğrudan ekleme oluşturma
  • Basitleştirilmiş Arama: Arama işlevlerinin doğrudan koleksiyonlarda kolayca oluşturulması
  • Birleştirilmiş Yapı: semantic_kernel.data.vector ve semantic_kernel.connectors altındaki her şey
  • Gelişmiş Metin Arama: Kolaylaştırılmış bağlayıcılarla geliştirilmiş metin arama özellikleri
  • Kullanımdan kaldırma: Eski memory_stores , yeni vektör deposu mimarisine göre kullanım dışı bırakıldı

1. Tümleşik Eklemeler ve Vektör Deposu Modelleri/Alanları Güncelleştirmeleri

Vektör deposu modelinizi tanımlama yönteminizde bir dizi değişiklik vardır, en büyük değişiklik artık doğrudan vektör deposu alan tanımlarına tümleşik eklemeleri desteklememizdir. Başka bir deyişle, vektör olacak bir alan belirttiğinizde, bu alanın içeriği OpenAI'nin metin ekleme modeli gibi belirtilen ekleme oluşturucu kullanılarak otomatik olarak eklenir. Bu, vektör alanlarını oluşturma ve yönetme sürecini basitleştirir.

Bu alanı tanımlarken, özellikle Pydantic modeli kullanırken üç şeyden emin olmanız gerekir:

  1. yazma: Alan muhtemelen üç türe sahip olacaktır. Ekleme oluşturucusunun girişi için list[float], str veya başka bir tür ve alan ayarlanmadığında None kullanılacaktır.
  2. varsayılan değer: Alanın varsayılan değeri None veya başka bir şey olmalıdır, böylece get artık varsayılan olduğunda search veya include_vectors=False kayıtları alınırken hata oluşmaz.

Burada iki sorun vardır. Birincisi, vectorstoremodel ile bir sınıfı süslerken, alanın ilk tür ek açıklamasının type sınıfının VectorStoreField parametresini doldurmak için kullanılmasıdır. Bu yüzden, ilk tür ek açıklamasının oluşturulacak vektör koleksiyonu için sıkça list[float] olduğu doğru tür olduğundan emin olmanız gerekir. Varsayılan olarak, get ve search yöntemleri sonuçlarda "include_vectors" içermediğinden, alanın varsayılan bir değere ihtiyacı vardır ve bu değere uygun bir yazım yapılmalıdır; bu nedenle çoğu zaman None'ye izin verilir ve varsayılan değer None olarak ayarlanır. Alan oluşturulduğunda, eklenmesi gereken değerler genellikle dizeler olmak üzere bu alana eklenir ve bu nedenle str de eklenmesi gerekir. Bu değişikliğin nedeni, eklenenler ve veri alanlarında depolananlar konusunda daha fazla esneklik sağlamaktır; bu yaygın bir kurulum olacaktır:

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}"

post_init yöntemine dikkat edin; bu, eklenmiş ve tek bir alandan daha fazlası olan bir değer oluşturur. Üç tür de mevcuttur.

Öncesi: Ayrı Alan Sınıfları

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")
]

Sonra: Entegre Gömmeler ile Birleştirilmiş VectorStoreField

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
    )
]

Alan Tanımındaki Önemli Değişiklikler

  1. Tek Alan Sınıfı: VectorStoreField Önceki tüm alan türlerinin yerini alır
  2. Alan Türü Belirtimi: Parametresini kullanın field_type: Literal["key", "data", "vector"] , bu konumsal bir parametre olabileceği için VectorStoreField("key") geçerlidir.
  3. Gelişmiş özellikler:
    • storage_name eklenmiştir; ayarlandığında, vektör deposunda alan adı olarak kullanılır, aksi takdirde name parametresi kullanılır.
    • dimensions artık vektör alanları için gerekli bir parametredir.
    • distance_function ve index_kind isteğe bağlıdır; belirtilmezlerse, yalnızca vektör alanları için DistanceFunction.DEFAULT ve IndexKind.DEFAULT olarak ayarlanırlar. Her vektör deposu uygulaması, kendi deposu için bir Varsayılan seçen bir mantığa sahiptir.
  4. Özellik Yeniden Adlandırmaları:
    • property_type type_ Öznitelik olarak ve type oluşturucularda
    • is_filterableis_indexed
    • is_full_text_searchableis_full_text_indexed
  5. Tümleşik Eklemeler: Doğrudan vektör alanlarına ekleyin embedding_generator ; alternatif olarak, bu depodaki tüm vektör alanları için kullanılacak olan vektör deposu koleksiyonunun kendisini ayarlayabilirsiniz embedding_generator ; bu değer koleksiyon düzeyi ekleme oluşturucusunun üzerinde önceliklidir.

2. Mağazalarda ve Koleksiyonlarda Yeni Yöntemler

Gelişmiş Mağaza Arabirimi

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.

Gelişmiş Koleksiyon Arabirimi

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)

Yeni vektör deposu uygulaması, dize tabanlı FilterClause nesnelerinden daha güçlü ve tür açısından güvenli lambda ifadelerine veya çağrılabilen filtrelere taşınır.

Önce: FilterClause Nesneleri

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)
)

Sonraki: Lambda İfade Filtreleri

# 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
)

Filtreler için Geçiş İpuçları

  1. Basit eşitlik: filter.equal_to("field", "value") olur lambda r: r.field == "value"
  2. Birden çok koşul: Birden çok filtre çağrısı yerine and/or işleçleriyle zincirleme
  3. Etiket/dizi kapsaması: filter.any_tag_equal_to("tags", "value") olur lambda r: "value" in r.tags
  4. Gelişmiş özellikler: Aralık sorguları, karmaşık boole mantığı ve özel koşul desteği

4. Geliştirilmiş Arama İşlevleri Oluşturma Kolaylığı

Önce: VectorStoreTextSearch ile arama işlevi oluşturma

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',
    ...
)

Sonra: Doğrudan Arama İşlevi Oluşturma

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. Bağlayıcıların Yeniden Adlandırılması ve İçeri Aktarma Değişiklikleri

Yol Birleştirmeyi İçeri Aktar

# 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
)

Bağlayıcı Sınıfının Yeniden Adlandırılması

Eski Adı Yeni Adı
AzureCosmosDBforMongoDB* CosmosMongo*
AzureCosmosDBForNoSQL* CosmosNoSql*

6. Metin Arama Geliştirmeleri ve Kaldırılan Bing Bağlayıcısı

Bing Arabulucusu Kaldırıldı ve Gelişmiş Metin Arama Arayüzü

Bing metin arama bağlayıcısı kaldırıldı. Alternatif arama sağlayıcılarına geçiş:

# 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)

Geliştirilmiş Arama Yöntemleri

Önce: Farklı dönüş türlerine sahip üç ayrı arama yöntemi

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,
)

Sonra: Çıkış türü parametresiyle birleşik arama yöntemi

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. Eski Bellek Depolarının Kullanımdan Kaldırılması

MemoryStoreBase temelli tüm eski bellek depoları semantic_kernel.connectors.memory_stores içine taşındı ve artık kullanım dışı olarak işaretlenmiş durumda. Çoğu, semantic_kernel.connectors.memory içinde bulunabilen VectorStore ve VectorStoreCollection'a dayalı eşdeğer yeni bir uygulamaya sahiptir.

Bu bağlayıcılar tamamen kaldırılır:

  • AstraDB
  • Milvus
  • Usearch

Bunlardan herhangi birine yine de ihtiyacınız varsa, kodu kullanım dışı bırakılan modülden ve klasöründen devraldığınızdan semantic_kernel.memory emin olun veya yeni sınıfa göre VectorStoreCollection.

Github geri bildirimlerini temel alan büyük bir talep varsa, bunları geri getirmeyi düşüneceğiz, ancak şimdilik bakım yapılmaz ve gelecekte kaldırılacaktır.

SemanticTextMemory'den geçiş

# 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"
)

Bellek Eklentisi Geçişi

Bilgileri de kaydedebilecek bir eklentiye sahip olmak istediğinizde, bunu aşağıdaki gibi kolayca oluşturabilirsiniz:

# 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")

1. Adım: İçeri Aktarmaları Güncelleştirme

  • [ ] Bellek deposu ithalatlarını vektör deposu eşdeğerleriyle değiştirin
  • [ ] Alan içeri aktarmalarını VectorStoreField olarak kullanacak şekilde güncelleştir
  • [ ] Bing bağlayıcı ithalatlarını kaldır

2. Adım: Alan Tanımlarını Güncelleştirme

  • [ ] Birleştirilmiş VectorStoreField sınıfa dönüştürme
  • [ ] Özellik adlarını güncelleştirme (is_filterableis_indexed)
  • [ ] Vektör alanlarına tümleşik ekleme oluşturucuları ekleme

3. Adım: Koleksiyon Kullanımını Güncelleştirme

  • [ ] Bellek işlemlerini vektör deposu yöntemleriyle değiştirme
  • [ ] Uygun olduğunda yeni toplu işlem kullan
  • [ ] Yeni arama işlevi oluşturulmasını uygula

4. Adım: Arama Uygulamasını Güncelleştirme

  • [ ] El ile arama işlevlerini şununla değiştirin: create_search_function
  • [ ] Metin aramasını yeni sağlayıcılar kullanacak şekilde güncelleştirme
  • [ ] Yararlı olduğu durumlarda karma arama uygulama
  • [ ] Filtreleme için FilterClause ifadelerinden lambda ifadelerine geçiş

5. Adım: Kullanım Dışı Kodu Kaldırma

  • SemanticTextMemory kullanımını kaldır [ ]
  • [ ] Bağımlılıkları kaldırma TextMemoryPlugin

Performans ve Özellik Avantajları

Performans Geliştirmeleri

  • Toplu İşlemler: Yeni batch upsert/delete yöntemleri aktarım hızını artırır
  • Tümleşik Eklemeler: Ayrı ekleme oluşturma adımlarını ortadan kaldırır
  • İyileştirilmiş Arama: Yerleşik arama işlevleri her mağaza türü için iyileştirilmiştir

Özellik Geliştirmeleri

  • Karma Arama: Daha iyi sonuçlar için vektör ve metin aramasını birleştirir
  • Gelişmiş Filtreleme: Gelişmiş filtre ifadeleri ve dizin oluşturma

Geliştirici Deneyimi

  • Basitleştirilmiş API: Öğrenmeniz gereken daha az sınıf ve yöntem
  • Tutarlı Arabirim: Tüm vektör depolarında birleşik yaklaşım
  • Daha İyi Belgeler: Açık örnekler ve geçiş yolları
  • Geleceğe Dayanıklı: Tutarlı platformlar arası geliştirme için .NET SDK ile uyumlu

Sonuç

Yukarıda açıklanan vektör deposu güncelleştirmeleri, Anlam Çekirdeği Python SDK'sında önemli bir gelişmeyi gösterir. Yeni birleşik mimari daha iyi performans, gelişmiş özellikler ve daha sezgisel bir geliştirici deneyimi sunar. Geçiş için içeri aktarmaların güncelleştirilmesi ve mevcut kodun yeniden düzenlenmesi gerekirken, bakım ve işlevsellik avantajları bu yükseltmenin kesinlikle önerilmesine neden olur.

Geçişle ilgili ek yardım için dizindeki güncelleştirilmiş örneklere samples/concepts/memory/ ve kapsamlı API belgelerine bakın.