Перенесите демо-примеры векторных данных Redis в общий индекс Azure AI Search.
Переместите поиск векторов LangGraph из демонстраций Redis в общий индекс Azure AI Search: определите схему, фильтруйте по сессии, удаляйте по запросу, сохраняя остальных пользователей.
Источники: 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 и ещё раз при обновлении модели вкладки. Несоответствия размеров измерений приводят к явным ошибкам; несоответствия фильтруемых полей проявляются скрыто в виде пустых наборов результатов. Добавьте операцию проверки при запуске, которая будет читать определение индекса и сравнивать размеры векторов и названия полей сессии с текущей конфигурацией.