Fix create, search vector store error (#13285)

* (#13284) add avector_store_create to route_type which doesn't require model

* (#13284) exclude hidden params in metadata when create vector store

* (#13284) fix lint error

* (#13284) keep metadata None if metadata is None(not empty dict)

* (#13284) add test code

* (#13284) change test code name

* (#13284) add avector_store_search to route_type which doesn't require model
This commit is contained in:
yeahyung
2025-08-06 11:15:17 -07:00
committed by GitHub
parent b1a8968895
commit a92bf8173e
4 changed files with 74 additions and 3 deletions
@@ -14,6 +14,7 @@ from litellm.types.vector_stores import (
VectorStoreSearchRequest,
VectorStoreSearchResponse,
)
from litellm.utils import add_openai_metadata
if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
@@ -119,12 +120,13 @@ class OpenAIVectorStoreConfig(BaseVectorStoreConfig):
api_base: str,
) -> Tuple[str, Dict]:
url = api_base # Base URL for creating vector stores
metadata = vector_store_create_optional_params.get("metadata", None)
typed_request_body = VectorStoreCreateRequest(
name=vector_store_create_optional_params.get("name", None),
file_ids=vector_store_create_optional_params.get("file_ids", None),
expires_after=vector_store_create_optional_params.get("expires_after", None),
chunking_strategy=vector_store_create_optional_params.get("chunking_strategy", None),
metadata=vector_store_create_optional_params.get("metadata", None),
metadata=add_openai_metadata(metadata) if metadata is not None else None,
)
dict_request_body = cast(dict, typed_request_body)
+2
View File
@@ -153,6 +153,8 @@ async def route_request(
"aget_responses",
"adelete_responses",
"alist_input_items",
"avector_store_create",
"avector_store_search",
]:
# moderation endpoint does not require `model` parameter
return getattr(llm_router, f"{route_type}")(**data)
@@ -0,0 +1,67 @@
import pytest
from litellm.llms.openai.vector_stores.transformation import OpenAIVectorStoreConfig
from litellm.types.vector_stores import (
VectorStoreCreateOptionalRequestParams,
)
class TestOpenAIVectorStoreAPIConfig:
@pytest.mark.parametrize(
"metadata", [{}, None]
)
def test_transform_create_vector_store_request_with_metadata_empty_or_none(self, metadata):
"""
Test transform_create_vector_store_request when metadata is None or empty dict.
"""
config = OpenAIVectorStoreConfig()
api_base = "https://api.openai.com/v1/vector_stores"
vector_store_create_params: VectorStoreCreateOptionalRequestParams = {
"name": "test-vector-store",
"file_ids": ["file-123", "file-456"],
"metadata": metadata,
}
url, request_body = config.transform_create_vector_store_request(
vector_store_create_params, api_base
)
assert url == api_base
assert request_body["name"] == "test-vector-store"
assert request_body["file_ids"] == ["file-123", "file-456"]
assert request_body["metadata"] == metadata
def test_transform_create_vector_store_request_with_large_metadata(self):
"""
Test transform_create_vector_store_request with metadata exceeding 16 keys.
OpenAI limits metadata to 16 keys maximum.
"""
config = OpenAIVectorStoreConfig()
api_base = "https://api.openai.com/v1/vector_stores"
# Create metadata with more than 16 keys
large_metadata = {f"key_{i}": f"value_{i}" for i in range(20)}
vector_store_create_params: VectorStoreCreateOptionalRequestParams = {
"name": "test-vector-store",
"metadata": large_metadata,
}
url, request_body = config.transform_create_vector_store_request(
vector_store_create_params, api_base
)
assert url == api_base
assert request_body["name"] == "test-vector-store"
# Should be trimmed to 16 keys
assert len(request_body["metadata"]) == 16
# Should contain the first 16 keys (as per add_openai_metadata implementation)
for i in range(16):
assert f"key_{i}" in request_body["metadata"]
assert request_body["metadata"][f"key_{i}"] == f"value_{i}"
@@ -49,7 +49,7 @@ async def test_route_request_dynamic_credentials(route_type):
@pytest.mark.asyncio
async def test_route_request_no_model_required():
"""Test route types that don't require model parameter"""
test_cases = ["amoderation", "aget_responses", "adelete_responses"]
test_cases = ["amoderation", "aget_responses", "adelete_responses", "avector_store_create", "avector_store_search"]
for route_type in test_cases:
# Test data without model parameter
@@ -72,7 +72,7 @@ async def test_route_request_no_model_required():
@pytest.mark.asyncio
async def test_route_request_no_model_required_with_router_settings():
"""Test route types that don't require model parameter with router settings"""
test_cases = ["amoderation", "aget_responses", "adelete_responses"]
test_cases = ["amoderation", "aget_responses", "adelete_responses", "avector_store_create", "avector_store_search"]
for route_type in test_cases:
# Test data with model parameter (it will be ignored for these route types)