Перемістіть демонстрації векторних даних Redis до спільного індексу Azure AI Search
Перемістіть пошук за векторами LangGraph з демонстрацій Redis у спільний індекс Azure AI Search: оголосіть схему, фільтруйте за сеансом, видаляйте за запитом, залиште інших користувачів.
Чому Redis не став кінцевою точкою
Локальний пошук векторів у Redis ідеально підходить для демонстрацій на ноутбуках. Однак спільні середовища, пошук з гарантованими показниками SLA та автентифікація, оптимізована під 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 restart redis clears state»
Результати та компроміси
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, а ще раз під час оновлення моделі ембеддингу. Невідповідності розмірів викликають явні помилки; невідповідності у фільтруваних полях проявляються лише у вигляді порожніх наборів результатів. Додайте вихідне твердження, яке читає визначення індексу та порівнює розміри векторів та назви полів сесії з поточною конфігурацією.