mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-02 06:22:48 +00:00
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:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
+67
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user