Skip to content

Commit 08fa87a

Browse files
authored
Make Cosmos vector index type configurable (default diskANN) (#24)
* Make Cosmos vector index type configurable (default diskANN) Add vector_index_type to create_memory_store (sync + async) and the AI_FOUNDRY_EMBEDDING_VECTOR_INDEX_TYPE env var, resolved via _resolve_vector_index_type with allow-list (diskANN, quantizedFlat, flat). Previously the memories container's vector index was hard-coded to diskANN, which blocked accounts without the DiskANN capability (e.g. the classic Cosmos DB emulator) and emulator-backed integration test pipelines. * Address review: append vector_index_type at end of create_memory_store Move the new optional vector_index_type parameter to the end of the create_memory_store signature (sync + async) so it does not shift the positional order of full_text_language/throughput_mode/autoscale_max_ru, preserving backwards compatibility for positional callers.
1 parent 127e86d commit 08fa87a

6 files changed

Lines changed: 90 additions & 1 deletion

File tree

.env.template

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ AI_FOUNDRY_EMBEDDING_DEPLOYMENT_NAME=text-embedding-3-large
5555
AI_FOUNDRY_EMBEDDING_DIMENSIONS=1536
5656
AI_FOUNDRY_EMBEDDING_DATA_TYPE=float32
5757
AI_FOUNDRY_EMBEDDING_DISTANCE_FUNCTION=cosine
58+
# Optional. Vector index type for the memories container: diskANN (default),
59+
# quantizedFlat, or flat. diskANN requires the DiskANN capability on the Cosmos
60+
# DB account; use quantizedFlat or flat for accounts without it (e.g. the
61+
# classic Cosmos DB emulator).
62+
AI_FOUNDRY_EMBEDDING_VECTOR_INDEX_TYPE=diskANN
5863
COSMOS_DB_FULL_TEXT_LANGUAGE=en-US
5964

6065
AI_FOUNDRY_CHAT_DEPLOYMENT_NAME=<your-model-deployment>

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
## Release History
22

3+
### Unreleased
4+
5+
#### Other Changes
6+
* The memories container's vector index type is now configurable instead of being
7+
hard-coded to `diskANN`. Set it via the `vector_index_type` argument to
8+
`create_memory_store(...)` or the `AI_FOUNDRY_EMBEDDING_VECTOR_INDEX_TYPE`
9+
environment variable. Allowed values are `diskANN` (default), `quantizedFlat`,
10+
and `flat`. This lets the toolkit run against Cosmos DB accounts without the
11+
DiskANN capability (for example the classic Cosmos DB emulator), enabling
12+
emulator-backed integration test pipelines.
13+
314
### 0.1.0b2 (2026-06-03)
415

516
#### Bugs Fixed

azure/cosmos/agent_memory/_utils.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ def _resolve_embedding_dimensions(val: Optional[int]) -> int:
175175

176176
_ALLOWED_EMBEDDING_DATA_TYPES = ("float32", "uint8", "int8")
177177
_ALLOWED_DISTANCE_FUNCTIONS = ("cosine", "dotproduct", "euclidean")
178+
_ALLOWED_VECTOR_INDEX_TYPES = ("diskANN", "quantizedFlat", "flat")
178179

179180

180181
def _resolve_embedding_data_type(val: Optional[str]) -> str:
@@ -211,6 +212,27 @@ def _resolve_distance_function(val: Optional[str]) -> str:
211212
return raw
212213

213214

215+
def _resolve_vector_index_type(val: Optional[str]) -> str:
216+
"""Resolve vector index type from explicit value or ``AI_FOUNDRY_EMBEDDING_VECTOR_INDEX_TYPE`` env var.
217+
218+
Defaults to ``diskANN``. Raises :class:`ConfigurationError` for unknown values.
219+
220+
``diskANN`` requires the Cosmos DB account to have the DiskANN vector index
221+
capability enabled. Accounts that do not (for example the classic Cosmos DB
222+
emulator) can use ``quantizedFlat`` or ``flat`` instead.
223+
"""
224+
raw = (val if val is not None else os.environ.get("AI_FOUNDRY_EMBEDDING_VECTOR_INDEX_TYPE") or "diskANN").strip()
225+
if raw not in _ALLOWED_VECTOR_INDEX_TYPES:
226+
raise ConfigurationError(
227+
message=(
228+
f"Invalid configuration for vector_index_type: must be one of "
229+
f"{_ALLOWED_VECTOR_INDEX_TYPES}, got {raw!r}"
230+
),
231+
parameter="vector_index_type",
232+
)
233+
return raw
234+
235+
214236
def _resolve_full_text_language(val: Optional[str]) -> str:
215237
"""Resolve full-text language from explicit value or ``COSMOS_DB_FULL_TEXT_LANGUAGE`` env var.
216238
@@ -368,6 +390,7 @@ def _container_policies(
368390
embedding_data_type: str,
369391
distance_function: str,
370392
full_text_language: str,
393+
vector_index_type: str = "diskANN",
371394
) -> tuple[dict, dict, dict]:
372395
"""Build the vector, indexing, and full-text policies for container creation."""
373396
vector_embedding_policy = {
@@ -388,7 +411,7 @@ def _container_policies(
388411
{"path": "/source_memory_ids/*"},
389412
{"path": "/supersedes_ids/*"},
390413
],
391-
"vectorIndexes": [{"path": "/embedding", "type": "diskANN"}],
414+
"vectorIndexes": [{"path": "/embedding", "type": vector_index_type}],
392415
"fullTextIndexes": [{"path": "/content"}],
393416
# Procedural synthesis selects TOP N by (salience DESC, created_at ASC, id ASC).
394417
# Cosmos requires a composite index for multi-property ORDER BY; without it the

azure/cosmos/agent_memory/aio/cosmos_memory_client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
_resolve_distance_function,
1919
_resolve_embedding_data_type,
2020
_resolve_full_text_language,
21+
_resolve_vector_index_type,
2122
_validate_connection,
2223
)
2324
from azure.cosmos.agent_memory.aio.auto_trigger import maybe_trigger_steps
@@ -263,6 +264,7 @@ async def create_memory_store(
263264
full_text_language: Optional[str] = None,
264265
throughput_mode: Optional[str] = None,
265266
autoscale_max_ru: Optional[int] = None,
267+
vector_index_type: Optional[str] = None,
266268
) -> None:
267269
"""Create the Cosmos DB database and memory/counter/lease containers."""
268270
self._cosmos_endpoint = endpoint or self._cosmos_endpoint
@@ -310,6 +312,7 @@ async def create_memory_store(
310312
embedding_data_type=_resolve_embedding_data_type(embedding_data_type),
311313
distance_function=_resolve_distance_function(distance_function),
312314
full_text_language=_resolve_full_text_language(full_text_language),
315+
vector_index_type=_resolve_vector_index_type(vector_index_type),
313316
)
314317
self._memories_container_client = await db.create_container_if_not_exists(
315318
**_build_container_kwargs(

azure/cosmos/agent_memory/cosmos_memory_client.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
_resolve_distance_function,
2020
_resolve_embedding_data_type,
2121
_resolve_full_text_language,
22+
_resolve_vector_index_type,
2223
_validate_connection,
2324
)
2425
from .auto_trigger import maybe_trigger_steps
@@ -235,6 +236,7 @@ def create_memory_store(
235236
full_text_language: Optional[str] = None,
236237
throughput_mode: Optional[str] = None,
237238
autoscale_max_ru: Optional[int] = None,
239+
vector_index_type: Optional[str] = None,
238240
) -> None:
239241
"""Create the Cosmos DB database and memory/counter/lease containers."""
240242
self._cosmos_endpoint = endpoint or self._cosmos_endpoint
@@ -281,6 +283,7 @@ def create_memory_store(
281283
embedding_data_type=_resolve_embedding_data_type(embedding_data_type),
282284
distance_function=_resolve_distance_function(distance_function),
283285
full_text_language=_resolve_full_text_language(full_text_language),
286+
vector_index_type=_resolve_vector_index_type(vector_index_type),
284287
)
285288
self._memories_container_client = db.create_container_if_not_exists(
286289
**_build_container_kwargs(

tests/unit/test_utils.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
from azure.cosmos.agent_memory._utils import (
66
DEFAULT_TTL_BY_TYPE,
77
_build_container_kwargs,
8+
_container_policies,
89
_make_memory,
910
_resolve_distance_function,
1011
_resolve_embedding_data_type,
1112
_resolve_full_text_language,
13+
_resolve_vector_index_type,
1214
compute_content_hash,
1315
)
1416
from azure.cosmos.agent_memory.exceptions import ConfigurationError, ValidationError
@@ -226,6 +228,48 @@ def test_resolve_distance_function_invalid_raises(monkeypatch):
226228
_resolve_distance_function(None)
227229

228230

231+
def test_resolve_vector_index_type_defaults(monkeypatch):
232+
monkeypatch.delenv("AI_FOUNDRY_EMBEDDING_VECTOR_INDEX_TYPE", raising=False)
233+
assert _resolve_vector_index_type(None) == "diskANN"
234+
235+
236+
def test_resolve_vector_index_type_from_env(monkeypatch):
237+
monkeypatch.setenv("AI_FOUNDRY_EMBEDDING_VECTOR_INDEX_TYPE", "quantizedFlat")
238+
assert _resolve_vector_index_type(None) == "quantizedFlat"
239+
240+
241+
def test_resolve_vector_index_type_explicit_overrides_env(monkeypatch):
242+
monkeypatch.setenv("AI_FOUNDRY_EMBEDDING_VECTOR_INDEX_TYPE", "quantizedFlat")
243+
assert _resolve_vector_index_type("flat") == "flat"
244+
245+
246+
def test_resolve_vector_index_type_invalid_raises(monkeypatch):
247+
monkeypatch.setenv("AI_FOUNDRY_EMBEDDING_VECTOR_INDEX_TYPE", "hnsw")
248+
with pytest.raises(ConfigurationError):
249+
_resolve_vector_index_type(None)
250+
251+
252+
def test_container_policies_defaults_to_diskann():
253+
_, indexing_policy, _ = _container_policies(
254+
embedding_dimensions=1536,
255+
embedding_data_type="float32",
256+
distance_function="cosine",
257+
full_text_language="en-US",
258+
)
259+
assert indexing_policy["vectorIndexes"] == [{"path": "/embedding", "type": "diskANN"}]
260+
261+
262+
def test_container_policies_uses_supplied_vector_index_type():
263+
_, indexing_policy, _ = _container_policies(
264+
embedding_dimensions=1536,
265+
embedding_data_type="float32",
266+
distance_function="cosine",
267+
full_text_language="en-US",
268+
vector_index_type="quantizedFlat",
269+
)
270+
assert indexing_policy["vectorIndexes"] == [{"path": "/embedding", "type": "quantizedFlat"}]
271+
272+
229273
def test_resolve_full_text_language_defaults(monkeypatch):
230274
monkeypatch.delenv("COSMOS_DB_FULL_TEXT_LANGUAGE", raising=False)
231275
assert _resolve_full_text_language(None) == "en-US"

0 commit comments

Comments
 (0)