Главная / Статьи

Перенесите демо-примеры векторных данных Redis в общий индекс Azure AI Search.

Переместите поиск векторов LangGraph из демонстраций Redis в общий индекс Azure AI Search: определите схему, фильтруйте по сессии, удаляйте по запросу, сохраняя остальных пользователей.

Издатель: REACTAPP.TOP6 мин чтения1396 слов

Источники: From Redis to Azure AI Search: The Full Migration

Почему Redis не стал окончательным решением

Локальный векторный поиск в Redis идеален для демонстраций на ноутбуках. Однако общие среды, поиск с гарантиями качества и встроенная система аутентификации от Azure побуждают команды использовать Azure AI Search. При такой миграции сохраняется конвейер LangGraph, но меняется векторный движок.

Традиционный поиск с ИИ против данного подхода

В классическом поиске по ключевым словам учитывается лексическое совпадение. В реализации после миграции эмбеддинги хранятся вместе с текстом, а поиск осуществляется на основе семантического сходства — при необходимости в сочетании с фильтрами. Azure AI Search становится централизованным хранилищем для таких векторов.

Единственное решение, которое пришлось изменить: общий индекс или индекс на уровне сессии

В демо-примерах Redis часто создается временный индекс для каждой сессии. Azure AI Search предпочитает использовать общий индекс с полем фильтрации по сессии (или аренде). Удаление всего индекса для «очистки сессии» — неправильный подход; правильным способом является удаление по фильтру.

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

Пошагово: что изменилось в коде

get_vector_store() — больше не ограничен сессией

Возвращается клиент, связанный с именем общего индекса. Изоляция сессий теперь реализуется через фильтры метаданных, а не через отдельные индексы.

Схема полей — объявляется явно

Размеры векторов, поля содержимого и идентификаторы сессий, подлежащие фильтрации, определяются заранее. Тихие значения по умолчанию, которые работали в Redis, не соответствуют типам полей в Azure AI Search.

retrieve_node — фильтр в виде строки вместо объекта-фильтра

Используйте формат session_id eq '…' (или эквивалентный фильтр OData), чтобы данные одного пользователя не попадали в результаты другого.

clear_session() — удаление по запросу, а не уничтожение индекса

Выполните фильтрованное удаление по ключу сессии. Пересоздание индексов для каждой сессии приведёт к превышению лимитов сервиса и замедлению запуска.

Чек-лист миграции

  • Соотнесите размер вектора эмбеддинга с полем векторного индекса
  • Переэмбеддинг выполняйте только в случае изменения модели эмбеддингов; в противном случае обновляйте существующие данные
  • Перед переходом протестируйте Redis и Azure AI Search на типовых запросах одновременно
  • По возможности переместите конфиденциальные данные в Key Vault или систему управляемой идентичности
  • Обновите руководства по эксплуатации: откажитесь от предположений вроде «перезапуск docker redis очищает состояние»

Результаты и компромиссы

Azure AI Search обеспечивает управляемую масштабируемость, инструменты портала и механизм RBAC. Кроме того, он вводит время на настройку ресурсов и ограничения, связанные с дизайном общих индексов. В случае графа вопросов и ответов в формате PDF структура узлов оставалась стабильной; изменились лишь адаптер хранилища и жизненный цикл сессий.

Рассматривайте Redis как вспомогательные элементы для обучения, а Azure AI Search — как основные компоненты для работы. Обеспечивайте изоляцию сессий с помощью фильтров, явно указывайте структуру данных и удаляйте записи по запросам. Система оркестрации LangGraph должна практически не замечать изменений; если же она их фиксирует, это означает, что уровень абстракции слишком низкий.

Совет по переходу: оставьте Redis в режиме только для чтения на протяжении недели, пока Azure AI Search обслуживает производственный трафик, и сравнивайте степень перекрытия результатов для трех наиболее важных вопросов из базы тестовых данных. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев во время миграции в этом случае связаны с ошибками фильтров, а не с проблемами векторной математики.

Совет при переходе: оставьте Redis в режиме только для чтения в течение недели, пока Azure AI Search обслуживает производственный трафик, сравнивая степень перекрытия результатов для топ-3 вхождений в идеальном наборе вопросов. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев при миграции в этом случае связаны с ошибками фильтров, а не с проблемами векторной математики.

Совет при переходе: оставьте Redis в режиме только для чтения в течение недели, пока Azure AI Search обслуживает производственный трафик, сравнивая степень перекрытия результатов для топ-3 вхождений в идеальном наборе вопросов. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев при миграции в этом случае связаны с ошибками фильтров, а не с проблемами векторной математики.

Совет при переходе: оставьте Redis в режиме только для чтения в течение недели, пока Azure AI Search обслуживает производственный трафик, сравнивая степень перекрытия результатов для топ-3 вспомогательного набора вопросов. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев в процессе миграции при таком подходе связаны с ошибками фильтров, а не с проблемами векторной математики.

Совет при переходе: оставьте Redis в режиме только для чтения в течение недели, пока Azure AI Search обслуживает производственный трафик, сравнивая степень перекрытия результатов для топ-3 вспомогательного набора вопросов. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев в процессе миграции при таком подходе связаны с ошибками фильтров, а не с проблемами векторной математики.

Совет при переходе: оставьте Redis в режиме только для чтения в течение недели, пока Azure AI Search обслуживает производственный трафик, сравнивая степень перекрытия результатов для топ-3 вспомогательного набора вопросов. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев в процессе миграции при таком подходе связаны с ошибками фильтров, а не с проблемами векторной математики.

Совет при переходе: оставьте Redis в режиме только для чтения в течение недели, пока Azure AI Search обслуживает производственный трафик, сравнивая степень перекрытия результатов для топ-3 вспомогательного набора вопросов. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев в процессе миграции при таком подходе связаны с ошибками фильтров, а не с проблемами векторной математики.

Совет при переходе: оставьте Redis в режиме только для чтения в течение недели, пока Azure AI Search обслуживает производственный трафик, сравнивая степень перекрытия результатов для топ-3 вхождений в идеальном наборе вопросов. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев при миграции в этом случае связаны с ошибками фильтров, а не с проблемами векторной математики.

Совет при переходе: оставьте Redis в режиме только для чтения в течение недели, пока Azure AI Search обслуживает производственный трафик, сравнивая степень перекрытия результатов для топ-3 вхождений в идеальном наборе вопросов. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев при миграции в этом случае связаны с ошибками фильтров, а не с проблемами векторной математики.

Совет при переходе: оставьте Redis в режиме только для чтения в течение недели, пока Azure AI Search обслуживает производственный трафик, сравнивая степень перекрытия результатов для топ-3 вспомогательного набора вопросов. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев в процессе миграции при таком подходе связаны с ошибками фильтров, а не с проблемами векторной математики.

Совет при переходе: оставьте Redis в режиме только для чтения в течение недели, пока Azure AI Search обслуживает производственный трафик, сравнивая степень перекрытия результатов для топ-3 вспомогательного набора вопросов. Если степень перекрытия снижается, проверьте условия фильтров и названия полей, прежде чем винить модель эмбеддингов. Большинство сбоев в процессе миграции при таком подходе связаны с ошибками фильтров, а не с проблемами векторной математики.

Схема дисциплины важна дважды: один раз при создании индекса Azure AI Search и ещё раз при обновлении модели вкладки. Несоответствия размеров измерений приводят к явным ошибкам; несоответствия фильтруемых полей проявляются скрыто в виде пустых наборов результатов. Добавьте операцию проверки при запуске, которая будет читать определение индекса и сравнивать размеры векторов и названия полей сессии с текущей конфигурацией.