Strona główna / Artykuły

Przenieś dema wektorowe Redis do wspólnego indeksu Azure AI Search

Przenieś wyszukiwanie wektorowe LangGraph z demonstracji Redis do wspólnego indeksu Azure AI Search: zadeklaruj schemat, filtrowaj według sesji, usuwaj na podstawie zapytania, zachowaj pozostałych użytkowników.

Wydawca: REACTAPP.TOP6 min czytania1396 słów

Źródła: From Redis to Azure AI Search: The Full Migration

Dlaczego Redis nie był ostatecznym rozwiązaniem

Lokalne wyszukiwanie wektorowe w Redis jest idealne do demonstracji na laptopach. Środowiska współdzielone, wyszukiwanie z gwarancjami SLA oraz autoryzacja typu Azure skłaniają zespoły do wyboru Azure AI Search. Ta migracja zachowuje pipeline LangGraph, ale zmienia backend wektorowy.

Klasyczne wyszukiwanie w AI Search kontra ten model

Klasyczne wyszukiwanie według słów kluczowych opiera się na pokryciu leksykalnym. W migrowanym podejściu embeddingi są przechowywane obok tekstu, a wyniki są wybierane na podstawie podobieństwa semantycznego – opcjonalnie w połączeniu z filtrami. Azure AI Search staje się zarządzanym miejscem przechowywania tych wektorów.

Jedna decyzja, która musiała ulec zmianie: wspólny indeks czy indeks na sesję

Demostracje z Redis często tworzą tymczasowy indeks na każdą sesję. Azure AI Search preferuje indeks współdzielony z polem filtrującym sesję (lub użytkownika). Usuwanie całego indeksu w celu „wyłączenia sesji” to niewłaściwe rozwiązanie; właściwym sposobem jest usuwanie według filtru.

uv add langgraph langchain-core langchain-openai langchain-text-splitters \
       azure-ai-documentintelligence azure-core \
       langchain-redis redisvl \
       python-dotenv
def get_vector_store() -> AzureSearch:
    global _vector_store
    if _vector_store is None:
        _vector_store = AzureSearch(
            azure_search_endpoint=config.AZURE_SEARCH_ENDPOINT,
            azure_search_key=config.AZURE_SEARCH_API_KEY,
            index_name=config.AZURE_SEARCH_INDEX_NAME,
            embedding_function=embeddings,
            fields=_FIELDS,
            vector_search_dimensions=config.EMBEDDING_DIMENSIONS,
        )
    return _vector_store
_FIELDS = [
    SimpleField(name="id", type=SearchFieldDataType.String, key=True, filterable=True),
    SearchableField(name="content", type=SearchFieldDataType.String),
    SearchField(
        name="content_vector",
        type="Collection(Edm.Single)",
        searchable=True,
        vector_search_dimensions=config.EMBEDDING_DIMENSIONS,
        vector_search_profile_name="myHnswProfile",
    ),
    SearchableField(name="metadata", type=SearchFieldDataType.String),
    SimpleField(name="session_id", type=SearchFieldDataType.String, filterable=True),
    SimpleField(name="file_name", type=SearchFieldDataType.String, filterable=True),
    SimpleField(name="chunk_index", type=SearchFieldDataType.Int32, filterable=True, sortable=True),
]
state["retrieved"] = vs.similarity_search(
    state["query"],
    k=config.TOP_K,
    filters=f"session_id eq '{state['session_id']}'",
)
def clear_session(session_id: str) -> None:
    vs = get_vector_store()
    results = vs.client.search(
        search_text="*",
        filter=f"session_id eq '{session_id}'",
        select=["id"],
    )
    ids = [r["id"] for r in results]
    if ids:
        vs.delete(ids=ids)
az search service create \
  --name "$SEARCH_SERVICE_NAME" \
  --resource-group "$RESOURCE_GROUP" \
  --location "$LOCATION" \
  --sku basic \
  --partition-count 1 \
  --replica-count 1

SEARCH_ADMIN_KEY=$(az search admin-key show \
  --resource-group "$RESOURCE_GROUP" \
  --service-name "$SEARCH_SERVICE_NAME" \
  --query primaryKey -o tsv)
AZURE_OPENAI_ENDPOINT=https://aif-cus-aisearchegs-dev-01.cognitiveservices.azure.com/
AZURE_OPENAI_API_KEY=<<redacted>>
# AZURE_OPENAI_API_VERSION = os.environ.get("AZURE_OPENAI_API_VERSION", "2024-10-21")
AZURE_OPENAI_EMBEDDING_DEPLOYMENT=text-embedding-3-small
AZURE_OPENAI_CHAT_DEPLOYMENT="gpt-5-mini"
# --- Azure Document Intelligence (used for all file text extraction) ---
DOCUMENTINTELLIGENCE_ENDPOINT=https://adi-cus-aisearchegs-dev-01.cognitiveservices.azure.com/
DOCUMENTINTELLIGENCE_KEY=<<redacted>>
AZURE_SEARCH_ENDPOINT=https://ais-cus-aisearchegs-dev-01.search.windows.net
AZURE_SEARCH_API_KEY=<<redacted>>
AZURE_SEARCH_INDEX_NAME=chat-file-search-index
azure.core.exceptions.HttpResponseError: The vector field 'content_vector'
must have the properties 'dimensions' and 'vectorSearchConfiguration' set.
TypeError: Object of type float32 is not JSON serializable
from azure.search.documents._utils.model_base import SdkJSONEncoder
_original_default = SdkJSONEncoder.default

def _numpy_safe_default(self, o):
    if isinstance(o, np.floating):
        return float(o)
    if isinstance(o, np.integer):
        return int(o)
    return _original_default(self, o)

SdkJSONEncoder.default = _numpy_safe_default
uv run python -m aisearchmanualvectorization.main \
  --session demo1 \
  --files ./source/sample_bank_statement.pdf ./source/sample_loan_agreement.pdf
uv run python -m aisearchmanualvectorization.main \
  --session demo1 \
  --query "What's the overdraft protection fee?"

A: The overdraft protection transfer fee is $10.00 per occurrence.

Sources:
  - sample_bank_statement.pdf (chunk 7): Overdraft Protection...
  - sample_bank_statement.pdf (chunk 8): Interest Rate & Annual Percentage Yield...
  - sample_bank_statement.pdf (chunk 9): Monthly Maintenance Fee...
  - sample_bank_statement.pdf (chunk 3): <td>-$10.44</td> <td>$8,096.52</td>...

Krok po kroku: co zmieniło się w kodzie

get_vector_store() — nie jest już ograniczony do sesji

Zwraca klient powiązany z nazwą indeksu współdzielonego. Izolacja sesji odbywa się poprzez filtry metadanych, a nie oddzielne indeksy.

Schemat pola — deklarowany wyraźnie

Z góry definiuje się wymiary wektorów, pola zawartości oraz identyfikatory sesji podlegające filtrowaniu. Ukryte domyślne wartości, które działały w Redis, nie będą pasować do typów pól w Azure AI Search.

retrieve_node — filtr w postaci ciągu znaków zamiast obiektu filtru

Użyj wyrażenia session_id eq '…' (lub równoważnego filtru OData), aby fragmenty jednego użytkownika nie przeniknęły do wyników innego.

clear_session() — usuwanie za pomocą zapytania, a nie niszczenie indeksu

Wykonaj usunięcie z filtrem dla klucza sesji. Ponowne tworzenie indeksów dla każdej sesji przekroczy limity usługi i spowolni proces uruchamiania.

Lista kontrolna migracji

  • Dostosuj wymiar embeddingu do pola wektora indeksu
  • Ponownie wstaw fragmenty tylko wtedy, gdy zmienił się model embeddingu; w przeciwnym razie zaktualizuj istniejące fragmenty
  • Zanim przeprowadzisz przeniesienie, uruchom Redis i Azure AI Search na przykładowych zapytaniach
  • Gdzie to możliwe, przenieś dane poufne do Key Vault lub zarządzanej tożsamości
  • Zaktualizuj instrukcje obsługi: nie zakładaj już, że „restart kontenera docker usunie stan Redis”

Wyniki i kompromisy

Azure AI Search wprowadza zarządzany skalowanie, narzędzia w portalu oraz mechanizm RBAC. Dodatkowo wprowadza czas przygotowania zasobów oraz ograniczenia związane z projektem wspólnych indeksów. W przypadku grafu pytań i odpowiedzi w formacie PDF struktura węzłów pozostała stabilna; zmieniły się jedynie adapter magazynowania i cykl życia sesji.

Zakończenie

Rozpatruj Redis jako koła pomocnicze, a Azure AI Search jako opony do jazdy po drodze. Zachowaj izolację sesji w filtrach, jasno zadeklaruj schemat danych i usuwaj elementy na podstawie zapytań. Orkiestracja LangGraph powinna ledwo to zauważyć – jeśli jednak tak się stanie, oznacza to, że abstrakcja była zbyt nieszczelna.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując najczęściej występujące pytania z zestawu referencyjnego. Jeśli stopień pokrycia spadnie, sprawdź klauzule filtrów i nazwy pól, zanim będziesz winić model embeddingu. Większość regresji podczas migracji w tym wzorcu wynika z błędów w filtrach, a nie z błędów w matematyce wektorowej.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując pokrycie najwyższych 3 wyników w bazie pytań referencyjnych. Jeśli pokrycie spadnie, sprawdź klauzule filtrów i nazwy pól, zanim obwiniesz model embeddingowy. Większość regresji podczas migracji w tym wzorcu to błędy filtrów, a nie błędy matematyki wektorowej.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując pokrycie najwyższych 3 wyników w bazie pytań referencyjnych. Jeśli pokrycie spadnie, sprawdź klauzule filtrów i nazwy pól, zanim obwiniś model embeddingowy. Większość regresji podczas migracji w tym wzorcu to błędy filtrów, a nie błędy matematyki wektorowej.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując pokrycie najlepszych 3 wyników w bazie pytań referencyjnych. Jeśli pokrycie spadnie, sprawdź klauzule filtrów i nazwy pól, zanim obwiniesz model embeddingowy. Większość regresji podczas migracji w tym wzorcu to błędy filtrów, a nie błędy matematyki wektorowej.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując pokrycie najlepszych 3 wyników w bazie pytań referencyjnych. Jeśli pokrycie spadnie, sprawdź klauzule filtrów i nazwy pól, zanim obwiniś model embeddingowy. Większość regresji podczas migracji w tym wzorcu to błędy filtrów, a nie błędy matematyki wektorowej.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując pokrycie najwyższych 3 wyników w bazie pytań referencyjnych. Jeśli pokrycie spadnie, sprawdź klauzule filtrów i nazwy pól, zanim obwini model embeddingowy. Większość regresji podczas migracji w tym wzorcu to błędy filtrów, a nie błędy matematyki wektorowej.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując pokrycie najwyższych 3 wyników w bazie pytań referencyjnych. Jeśli pokrycie spadnie, sprawdź klauzule filtrów i nazwy pól, zanim obwini model embeddingowy. Większość regresji podczas migracji w tym wzorcu to błędy filtrów, a nie błędy matematyki wektorowej.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując pokrycie najwyższych 3 wyników w bazie pytań referencyjnych. Jeśli pokrycie spadnie, sprawdź klauzule filtrów i nazwy pól, zanim obwiniesz model embeddingowy. Większość regresji podczas migracji w tym wzorcu to błędy filtrów, a nie błędy matematyki wektorowej.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując pokrycie najwyższych 3 wyników w bazie pytań referencyjnych. Jeśli pokrycie spadnie, sprawdź klauzule filtrów i nazwy pól, zanim obwiniś model embeddingowy. Większość regresji podczas migracji w tym wzorcu to błędy filtrów, a nie błędy matematyki wektorowej.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując pokrycie najwyższych 3 wyników w bazie pytań referencyjnych. Jeśli pokrycie spadnie, sprawdź klauzule filtrów i nazwy pól, zanim obwiniesz model embeddingowy. Większość regresji podczas migracji w tym wzorcu to błędy filtrów, a nie błędy matematyki wektorowej.

Wskazówka przy przenoszeniu: utrzymuj Redis w trybie tylko do odczytu przez tydzień, podczas gdy Azure AI Search obsługuje ruch produkcyjny, porównując pokrycie najwyższych 3 wyników w bazie pytań referencyjnych. Jeśli pokrycie spadnie, sprawdź klauzule filtrów i nazwy pól, zanim obwiniś model embeddingowy. Większość regresji podczas migracji w tym wzorcu to błędy filtrów, a nie błędy matematyki wektorowej.

Schemat dyscypliny ma znaczenie dwa razy: raz podczas tworzenia indeksu Azure AI Search, a ponownie przy aktualizacji modelu embeddingów. Niezgodności wymiarów powodują wyraźne błędy; niezgodności pól, które można filtrować, dają się zauważyć jedynie poprzez puste zestawy wyników. Należy dodać operację weryfikacyjną przy uruchamianiu, która odczytuje definicję indeksu i porównuje wymiary wektorów oraz nazwy pól sesji z aktualną konfiguracją.