diff --git a/docs/my-website/docs/providers/bedrock_vector_store.md b/docs/my-website/docs/providers/bedrock_vector_store.md
index 39e1aec5ab83..5fae0c76c11a 100644
--- a/docs/my-website/docs/providers/bedrock_vector_store.md
+++ b/docs/my-website/docs/providers/bedrock_vector_store.md
@@ -138,6 +138,125 @@ print(response.choices[0].message.content)
+## Filter Results
+
+Filter by metadata attributes.
+
+**Operators** (OpenAI-style, auto-translated):
+- `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`
+
+**AWS operators** (use directly):
+- `equals`, `notEquals`, `greaterThan`, `greaterThanOrEquals`, `lessThan`, `lessThanOrEquals`, `in`, `notIn`, `startsWith`, `listContains`, `stringContains`
+
+
+
+
+```python
+response = await litellm.acompletion(
+ model="anthropic/claude-3-5-sonnet",
+ messages=[{"role": "user", "content": "What are the latest updates?"}],
+ tools=[{
+ "type": "file_search",
+ "vector_store_ids": ["YOUR_KNOWLEDGE_BASE_ID"],
+ "filters": {
+ "key": "category",
+ "value": "updates",
+ "operator": "eq"
+ }
+ }]
+)
+```
+
+
+
+
+
+```python
+response = await litellm.acompletion(
+ model="anthropic/claude-3-5-sonnet",
+ messages=[{"role": "user", "content": "What are the policies?"}],
+ tools=[{
+ "type": "file_search",
+ "vector_store_ids": ["YOUR_KNOWLEDGE_BASE_ID"],
+ "filters": {
+ "and": [
+ {"key": "category", "value": "policy", "operator": "eq"},
+ {"key": "year", "value": 2024, "operator": "gte"}
+ ]
+ }
+ }]
+)
+```
+
+
+
+
+
+```python
+response = await litellm.acompletion(
+ model="anthropic/claude-3-5-sonnet",
+ messages=[{"role": "user", "content": "Show me technical docs"}],
+ tools=[{
+ "type": "file_search",
+ "vector_store_ids": ["YOUR_KNOWLEDGE_BASE_ID"],
+ "filters": {
+ "or": [
+ {"key": "category", "value": "api", "operator": "eq"},
+ {"key": "category", "value": "sdk", "operator": "eq"}
+ ]
+ }
+ }]
+)
+```
+
+
+
+
+
+```python
+response = await litellm.acompletion(
+ model="anthropic/claude-3-5-sonnet",
+ messages=[{"role": "user", "content": "Find docs"}],
+ tools=[{
+ "type": "file_search",
+ "vector_store_ids": ["YOUR_KNOWLEDGE_BASE_ID"],
+ "filters": {
+ "and": [
+ {"key": "title", "value": "Guide", "operator": "stringContains"},
+ {"key": "tags", "value": "important", "operator": "listContains"}
+ ]
+ }
+ }]
+)
+```
+
+
+
+
+
+```bash
+curl http://localhost:4000/v1/chat/completions \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer $LITELLM_API_KEY" \
+ -d '{
+ "model": "claude-3-5-sonnet",
+ "messages": [{"role": "user", "content": "What are our policies?"}],
+ "tools": [{
+ "type": "file_search",
+ "vector_store_ids": ["YOUR_KNOWLEDGE_BASE_ID"],
+ "filters": {
+ "and": [
+ {"key": "department", "value": "engineering", "operator": "eq"},
+ {"key": "type", "value": "policy", "operator": "eq"}
+ ]
+ }
+ }]
+ }'
+```
+
+
+
+
## Accessing Search Results
See how to access vector store search results in your response:
diff --git a/litellm/llms/base_llm/vector_store/transformation.py b/litellm/llms/base_llm/vector_store/transformation.py
index 9d7ba7d61a8e..8bb54f048757 100644
--- a/litellm/llms/base_llm/vector_store/transformation.py
+++ b/litellm/llms/base_llm/vector_store/transformation.py
@@ -2,9 +2,11 @@
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
import httpx
+from numpy import isin
from litellm.types.router import GenericLiteLLMParams
from litellm.types.vector_stores import (
+ VECTOR_STORE_OPENAI_PARAMS,
VectorStoreCreateOptionalRequestParams,
VectorStoreCreateResponse,
VectorStoreSearchOptionalRequestParams,
@@ -24,6 +26,20 @@
class BaseVectorStoreConfig:
+
+ def get_supported_openai_params(
+ self, model: str
+ ) -> List[VECTOR_STORE_OPENAI_PARAMS]:
+ return []
+
+ def map_openai_params(
+ self,
+ non_default_params: dict,
+ optional_params: dict,
+ drop_params: bool,
+ ) -> dict:
+ return optional_params
+
@abstractmethod
def transform_search_vector_store_request(
self,
@@ -34,6 +50,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
) -> Tuple[str, Dict]:
+
pass
@abstractmethod
diff --git a/litellm/llms/bedrock/vector_stores/transformation.py b/litellm/llms/bedrock/vector_stores/transformation.py
index c05b6ba3fb1e..c485defe8a81 100644
--- a/litellm/llms/bedrock/vector_stores/transformation.py
+++ b/litellm/llms/bedrock/vector_stores/transformation.py
@@ -13,6 +13,7 @@
)
from litellm.types.router import GenericLiteLLMParams
from litellm.types.vector_stores import (
+ VECTOR_STORE_OPENAI_PARAMS,
VectorStoreResultContent,
VectorStoreSearchOptionalRequestParams,
VectorStoreSearchResponse,
@@ -32,6 +33,134 @@ def __init__(self) -> None:
BaseVectorStoreConfig.__init__(self)
BaseAWSLLM.__init__(self)
+ def get_supported_openai_params(
+ self, model: str
+ ) -> List[VECTOR_STORE_OPENAI_PARAMS]:
+ return ["filters", "max_num_results", "ranking_options"]
+
+ def _map_operator_to_aws(self, operator: str) -> str:
+ """
+ Map OpenAI-style operators to AWS Bedrock operator names.
+
+ OpenAI uses: eq, ne, gt, gte, lt, lte, in, nin
+ AWS uses: equals, notEquals, greaterThan, greaterThanOrEquals, lessThan, lessThanOrEquals, in, notIn, startsWith, listContains, stringContains
+ """
+ operator_mapping = {
+ "eq": "equals",
+ "ne": "notEquals",
+ "gt": "greaterThan",
+ "gte": "greaterThanOrEquals",
+ "lt": "lessThan",
+ "lte": "lessThanOrEquals",
+ "in": "in",
+ "nin": "notIn",
+ # AWS-specific operators (pass through)
+ "equals": "equals",
+ "notEquals": "notEquals",
+ "greaterThan": "greaterThan",
+ "greaterThanOrEquals": "greaterThanOrEquals",
+ "lessThan": "lessThan",
+ "lessThanOrEquals": "lessThanOrEquals",
+ "notIn": "notIn",
+ "startsWith": "startsWith",
+ "listContains": "listContains",
+ "stringContains": "stringContains",
+ }
+ return operator_mapping.get(operator, operator)
+
+ def _map_operator_filter(self, filter_dict: dict) -> dict:
+ """
+ Map a single OpenAI operator filter to AWS KB format.
+
+ OpenAI format: {"key": , "value": , "operator": }
+ AWS KB format: {"operator": {"key": , "value": }}
+ """
+ aws_operator = self._map_operator_to_aws(filter_dict["operator"])
+ return {
+ aws_operator: {
+ "key": filter_dict["key"],
+ "value": filter_dict["value"],
+ }
+ }
+
+ def _map_and_or_filters(self, value: dict) -> dict:
+ """
+ Map OpenAI and/or filters to AWS KB format.
+
+ OpenAI format: {"and" | "or": [{"key": , "value": , "operator": }]}
+ AWS KB format: {"andAll" | "orAll": [{"operator": {"key": , "value": }}]}
+
+ Note: AWS requires andAll/orAll to have at least 2 elements.
+ For single filters, unwrap and return just the operator.
+ """
+ aws_filters = {}
+
+ if "and" in value:
+ and_filters = value["and"]
+ # If only 1 filter, return just the operator (AWS requires andAll to have >=2 elements)
+ if len(and_filters) == 1:
+ return self._map_operator_filter(and_filters[0])
+
+ aws_filters["andAll"] = [
+ {
+ self._map_operator_to_aws(and_filters[i]["operator"]): {
+ "key": and_filters[i]["key"],
+ "value": and_filters[i]["value"],
+ }
+ }
+ for i in range(len(and_filters))
+ ]
+
+ if "or" in value:
+ or_filters = value["or"]
+ # If only 1 filter, return just the operator (AWS requires orAll to have >=2 elements)
+ if len(or_filters) == 1:
+ return self._map_operator_filter(or_filters[0])
+
+ aws_filters["orAll"] = [
+ {
+ self._map_operator_to_aws(or_filters[i]["operator"]): {
+ "key": or_filters[i]["key"],
+ "value": or_filters[i]["value"],
+ }
+ }
+ for i in range(len(or_filters))
+ ]
+
+ return aws_filters
+
+ def map_openai_params(
+ self,
+ non_default_params: dict,
+ optional_params: dict,
+ drop_params: bool,
+ ) -> dict:
+ for param, value in non_default_params.items():
+ if param == "max_num_results":
+ optional_params["numberOfResults"] = value
+ elif param == "filters" and value is not None:
+
+ # map the openai filters to the aws kb filters format
+ # openai filters = {"key": , "value": , "operator": } OR {"and" | "or": [{"key": , "value": , "operator": }]}
+ # aws kb filters = {"operator": {"": }} OR {"andAll | orAll": [{"operator": {"": }}]}
+ # 1. check if filter is in openai format
+ # 2. if it is, map it to the aws kb filters format
+ # 3. if it is not, assume it is in aws kb filters format and add it to the optional_params
+ aws_filters: Optional[Dict] = None
+
+ if isinstance(value, dict):
+ if "operator" in value.keys():
+ # Single operator - map directly (no wrapping needed)
+ aws_filters = self._map_operator_filter(value)
+ elif "and" in value.keys() or "or" in value.keys():
+ aws_filters = self._map_and_or_filters(value)
+ else:
+ # Assume it's already in AWS KB format
+ aws_filters = value
+ optional_params["filters"] = aws_filters
+
+ return optional_params
+
def validate_environment(
self, headers: dict, litellm_params: Optional[GenericLiteLLMParams]
) -> dict:
@@ -39,13 +168,13 @@ def validate_environment(
headers.setdefault("Content-Type", "application/json")
return headers
- def get_complete_url(
- self, api_base: Optional[str], litellm_params: dict
- ) -> str:
+ def get_complete_url(self, api_base: Optional[str], litellm_params: dict) -> str:
aws_region_name = litellm_params.get("aws_region_name")
endpoint_url, _ = self.get_runtime_endpoint(
api_base=api_base,
- aws_bedrock_runtime_endpoint=litellm_params.get("aws_bedrock_runtime_endpoint"),
+ aws_bedrock_runtime_endpoint=litellm_params.get(
+ "aws_bedrock_runtime_endpoint"
+ ),
aws_region_name=self.get_aws_region_name_for_non_llm_api_calls(
aws_region_name=aws_region_name
),
@@ -86,7 +215,9 @@ def transform_search_vector_store_request(
# Create a properly typed retrieval configuration
typed_retrieval_config: BedrockKBRetrievalConfiguration = {}
if "vectorSearchConfiguration" in retrieval_config:
- typed_retrieval_config["vectorSearchConfiguration"] = retrieval_config["vectorSearchConfiguration"]
+ typed_retrieval_config["vectorSearchConfiguration"] = retrieval_config[
+ "vectorSearchConfiguration"
+ ]
request_body["retrievalConfiguration"] = typed_retrieval_config
litellm_logging_obj.model_call_details["query"] = query
@@ -117,8 +248,12 @@ def _get_file_id_from_metadata(self, metadata: Dict[str, Any]) -> str:
source_uri = metadata.get("x-amz-bedrock-kb-source-uri", "") if metadata else ""
if source_uri:
return source_uri
-
- chunk_id = metadata.get("x-amz-bedrock-kb-chunk-id", "unknown") if metadata else "unknown"
+
+ chunk_id = (
+ metadata.get("x-amz-bedrock-kb-chunk-id", "unknown")
+ if metadata
+ else "unknown"
+ )
return f"bedrock-kb-{chunk_id}"
def _get_filename_from_metadata(self, metadata: Dict[str, Any]) -> str:
@@ -127,18 +262,26 @@ def _get_filename_from_metadata(self, metadata: Dict[str, Any]) -> str:
Tries to extract filename from source URI, falls back to domain name or data source ID.
"""
source_uri = metadata.get("x-amz-bedrock-kb-source-uri", "") if metadata else ""
-
+
if source_uri:
try:
parsed_uri = urlparse(source_uri)
- filename = parsed_uri.path.split('/')[-1] if parsed_uri.path and parsed_uri.path != '/' else parsed_uri.netloc
- if not filename or filename == '/':
+ filename = (
+ parsed_uri.path.split("/")[-1]
+ if parsed_uri.path and parsed_uri.path != "/"
+ else parsed_uri.netloc
+ )
+ if not filename or filename == "/":
filename = parsed_uri.netloc
return filename
except Exception:
return source_uri
-
- data_source_id = metadata.get("x-amz-bedrock-kb-data-source-id", "unknown") if metadata else "unknown"
+
+ data_source_id = (
+ metadata.get("x-amz-bedrock-kb-data-source-id", "unknown")
+ if metadata
+ else "unknown"
+ )
return f"bedrock-kb-document-{data_source_id}"
def _get_attributes_from_metadata(self, metadata: Dict[str, Any]) -> Dict[str, Any]:
@@ -161,13 +304,13 @@ def transform_search_vector_store_response(
text = content.get("text") if content else None
if text is None:
continue
-
+
# Extract metadata and use helper functions
metadata = item.get("metadata", {}) or {}
file_id = self._get_file_id_from_metadata(metadata)
filename = self._get_filename_from_metadata(metadata)
attributes = self._get_attributes_from_metadata(metadata)
-
+
results.append(
VectorStoreSearchResult(
score=item.get("score"),
diff --git a/litellm/llms/custom_httpx/llm_http_handler.py b/litellm/llms/custom_httpx/llm_http_handler.py
index b67e8823d0cf..758d6669c025 100644
--- a/litellm/llms/custom_httpx/llm_http_handler.py
+++ b/litellm/llms/custom_httpx/llm_http_handler.py
@@ -1593,8 +1593,6 @@ def search(
headers=headers or {},
)
-
-
# Transform the request
data = provider_config.transform_search_request(
query=query,
@@ -1682,7 +1680,7 @@ async def async_search(
query=query,
optional_params=optional_params,
)
-
+
# Get complete URL (pass data for providers that need request body for URL construction)
complete_url = provider_config.get_complete_url(
api_base=api_base,
@@ -1704,6 +1702,7 @@ async def async_search(
if client is None or not isinstance(client, AsyncHTTPHandler):
# For search providers, use special Search provider type
from litellm.types.llms.custom_http import httpxSpecialProvider
+
async_httpx_client = get_async_httpx_client(
llm_provider=httpxSpecialProvider.Search
)
@@ -1726,7 +1725,7 @@ async def async_search(
response = await async_httpx_client.post(
url=complete_url,
headers=headers,
- json=data,
+ json=data, # type: ignore
timeout=timeout,
)
except Exception as e:
@@ -4074,16 +4073,16 @@ def video_generation_handler(
try:
# Use JSON when no files, otherwise use form data with files
if files and len(files) > 0:
- # Use multipart/form-data when files are present
- response = sync_httpx_client.post(
- url=api_base,
- headers=headers,
- data=data,
- files=files,
- timeout=timeout,
- )
+ # Use multipart/form-data when files are present
+ response = sync_httpx_client.post(
+ url=api_base,
+ headers=headers,
+ data=data,
+ files=files,
+ timeout=timeout,
+ )
- # --- END MOCK VIDEO RESPONSE ---
+ # --- END MOCK VIDEO RESPONSE ---
else:
response = sync_httpx_client.post(
url=api_base,
@@ -4350,7 +4349,7 @@ async def async_video_content_handler(
e=e,
provider_config=video_content_provider_config,
)
-
+
def video_remix_handler(
self,
video_id: str,
@@ -4577,6 +4576,7 @@ def video_list_handler(
else:
# For sync calls, we'll use the async handler in a sync context
import asyncio
+
return asyncio.run(
self.async_video_list_handler(
after=after,
@@ -4677,7 +4677,7 @@ async def async_video_list_handler(
e=e,
provider_config=video_list_provider_config,
)
-
+
async def async_video_delete_handler(
self,
video_id: str,
@@ -4815,12 +4815,14 @@ def video_status_handler(
)
# Transform the request using the provider config
- url, data = video_status_provider_config.transform_video_status_retrieve_request(
- video_id=video_id,
- model=model,
- api_base=api_base,
- litellm_params=litellm_params,
- headers=headers,
+ url, data = (
+ video_status_provider_config.transform_video_status_retrieve_request(
+ video_id=video_id,
+ model=model,
+ api_base=api_base,
+ litellm_params=litellm_params,
+ headers=headers,
+ )
)
## LOGGING
@@ -4840,10 +4842,12 @@ def video_status_handler(
headers=headers,
)
- return video_status_provider_config.transform_video_status_retrieve_response(
- model=model,
- raw_response=response,
- logging_obj=logging_obj,
+ return (
+ video_status_provider_config.transform_video_status_retrieve_response(
+ model=model,
+ raw_response=response,
+ logging_obj=logging_obj,
+ )
)
except Exception as e:
@@ -4893,12 +4897,14 @@ async def async_video_status_handler(
)
# Transform the request using the provider config
- url, data = video_status_provider_config.transform_video_status_retrieve_request(
- video_id=video_id,
- model=model,
- api_base=api_base,
- litellm_params=litellm_params,
- headers=headers,
+ url, data = (
+ video_status_provider_config.transform_video_status_retrieve_request(
+ video_id=video_id,
+ model=model,
+ api_base=api_base,
+ litellm_params=litellm_params,
+ headers=headers,
+ )
)
## LOGGING
@@ -4918,10 +4924,12 @@ async def async_video_status_handler(
headers=headers,
)
- return video_status_provider_config.transform_video_status_retrieve_response(
- model=model,
- raw_response=response,
- logging_obj=logging_obj,
+ return (
+ video_status_provider_config.transform_video_status_retrieve_response(
+ model=model,
+ raw_response=response,
+ logging_obj=logging_obj,
+ )
)
except Exception as e:
@@ -5001,6 +5009,7 @@ async def async_vector_store_search_handler(
)
try:
+
response = await async_httpx_client.post(
url=url,
headers=headers,
diff --git a/litellm/proxy/_new_secret_config.yaml b/litellm/proxy/_new_secret_config.yaml
index 318cb56619b9..dae07760557b 100644
--- a/litellm/proxy/_new_secret_config.yaml
+++ b/litellm/proxy/_new_secret_config.yaml
@@ -1,29 +1,13 @@
-model_list:
- - model_name: gpt-5-mini
- litellm_params:
- model: bedrock/global.anthropic.claude-sonnet-4-5-20250929-v1:0
- - model_name: embedding-model
+model_list:
+ - model_name: claude-3-5-sonnet
litellm_params:
- model: azure/text-embedding-3-large
- api_base: https://krris-mh44uf7y-eastus2.cognitiveservices.azure.com/
- api_key: os.environ/AZURE_API_KEY
- api_version: "2025-09-01"
+ model: anthropic/claude-3-5-sonnet-20240620
+ api_key: os.environ/ANTHROPIC_API_KEY
-guardrails:
- - guardrail_name: "enkryptai-guard"
+vector_store_registry:
+ - vector_store_name: "bedrock-company-docs"
litellm_params:
- guardrail: enkryptai
- mode: "pre_call"
- api_key: os.environ/ENKRYPTAI_API_KEY
- default_on: true
- policy_name: "Sample Airline Guardrail"
- detectors:
- toxicity:
- enabled: true
- nsfw:
- enabled: true
- pii:
- enabled: true
- entities: ["email", "phone", "secrets"]
- injection_attack:
- enabled: true
+ vector_store_id: "HNYBPIYVWK"
+ custom_llm_provider: "bedrock"
+ vector_store_description: "Bedrock Knowledge Base for company documents"
+ filters: {"and": [{"key": "category", "value": "company", "operator": "eq"}]}
\ No newline at end of file
diff --git a/litellm/types/vector_stores.py b/litellm/types/vector_stores.py
index 58a2e7f90062..144b1853382f 100644
--- a/litellm/types/vector_stores.py
+++ b/litellm/types/vector_stores.py
@@ -76,6 +76,7 @@ class VectorStoreResultContent(TypedDict, total=False):
class VectorStoreSearchResult(TypedDict, total=False):
"""Result of a vector store search"""
+
score: Optional[float]
content: Optional[List[VectorStoreResultContent]]
file_id: Optional[str]
@@ -92,44 +93,55 @@ class VectorStoreSearchResponse(TypedDict, total=False):
search_query: Optional[str]
data: Optional[List[VectorStoreSearchResult]]
+
class VectorStoreSearchOptionalRequestParams(TypedDict, total=False):
"""TypedDict for Optional parameters supported by the vector store search API."""
+
filters: Optional[Dict]
- max_num_results: Optional[int]
+ max_num_results: Optional[int]
ranking_options: Optional[Dict]
rewrite_query: Optional[bool]
+
class VectorStoreSearchRequest(VectorStoreSearchOptionalRequestParams, total=False):
"""Request body for searching a vector store"""
+
query: Union[str, List[str]]
# Vector Store Creation Types
class VectorStoreExpirationPolicy(TypedDict, total=False):
"""The expiration policy for a vector store"""
- anchor: Literal["last_active_at"] # Anchor timestamp after which the expiration policy applies
+
+ anchor: Literal[
+ "last_active_at"
+ ] # Anchor timestamp after which the expiration policy applies
days: int # Number of days after anchor time that the vector store will expire
class VectorStoreAutoChunkingStrategy(TypedDict, total=False):
"""Auto chunking strategy configuration"""
+
type: Literal["auto"] # Always "auto"
class VectorStoreStaticChunkingStrategyConfig(TypedDict, total=False):
"""Static chunking strategy configuration"""
+
max_chunk_size_tokens: int # Maximum number of tokens per chunk
chunk_overlap_tokens: int # Number of tokens to overlap between chunks
class VectorStoreStaticChunkingStrategy(TypedDict, total=False):
"""Static chunking strategy"""
+
type: Literal["static"] # Always "static"
static: VectorStoreStaticChunkingStrategyConfig
class VectorStoreChunkingStrategy(TypedDict, total=False):
"""Union type for chunking strategies"""
+
# This can be either auto or static
type: Literal["auto", "static"]
static: Optional[VectorStoreStaticChunkingStrategyConfig]
@@ -137,6 +149,7 @@ class VectorStoreChunkingStrategy(TypedDict, total=False):
class VectorStoreFileCounts(TypedDict, total=False):
"""File counts for a vector store"""
+
in_progress: int
completed: int
failed: int
@@ -146,20 +159,27 @@ class VectorStoreFileCounts(TypedDict, total=False):
class VectorStoreCreateOptionalRequestParams(TypedDict, total=False):
"""TypedDict for Optional parameters supported by the vector store create API."""
+
name: Optional[str] # Name of the vector store
file_ids: Optional[List[str]] # List of File IDs that the vector store should use
- expires_after: Optional[VectorStoreExpirationPolicy] # Expiration policy for the vector store
- chunking_strategy: Optional[VectorStoreChunkingStrategy] # Chunking strategy for the files
+ expires_after: Optional[
+ VectorStoreExpirationPolicy
+ ] # Expiration policy for the vector store
+ chunking_strategy: Optional[
+ VectorStoreChunkingStrategy
+ ] # Chunking strategy for the files
metadata: Optional[Dict[str, str]] # Set of key-value pairs for metadata
class VectorStoreCreateRequest(VectorStoreCreateOptionalRequestParams, total=False):
"""Request body for creating a vector store"""
+
pass # All fields are optional for vector store creation
class VectorStoreCreateResponse(TypedDict, total=False):
"""Response after creating a vector store"""
+
id: str # ID of the vector store
object: Literal["vector_store"] # Always "vector_store"
created_at: int # Unix timestamp of when the vector store was created
@@ -169,5 +189,15 @@ class VectorStoreCreateResponse(TypedDict, total=False):
status: Literal["expired", "in_progress", "completed"] # Status of the vector store
expires_after: Optional[VectorStoreExpirationPolicy] # Expiration policy
expires_at: Optional[int] # Unix timestamp of when the vector store expires
- last_active_at: Optional[int] # Unix timestamp of when the vector store was last active
- metadata: Optional[Dict[str, str]] # Metadata associated with the vector store
\ No newline at end of file
+ last_active_at: Optional[
+ int
+ ] # Unix timestamp of when the vector store was last active
+ metadata: Optional[Dict[str, str]] # Metadata associated with the vector store
+
+
+VECTOR_STORE_OPENAI_PARAMS = Literal[
+ "filters",
+ "max_num_results",
+ "ranking_options",
+ "rewrite_query",
+]
diff --git a/litellm/vector_stores/main.py b/litellm/vector_stores/main.py
index a0d0e338edc4..5915044536c9 100644
--- a/litellm/vector_stores/main.py
+++ b/litellm/vector_stores/main.py
@@ -430,7 +430,8 @@ def search(
# Get VectorStoreSearchOptionalRequestParams with only valid parameters
vector_store_search_optional_params: VectorStoreSearchOptionalRequestParams = (
VectorStoreRequestUtils.get_requested_vector_store_search_optional_param(
- local_vars
+ local_vars,
+ vector_store_provider_config=vector_store_provider_config,
)
)
diff --git a/litellm/vector_stores/utils.py b/litellm/vector_stores/utils.py
index b7eb7790adde..9430c68ccc94 100644
--- a/litellm/vector_stores/utils.py
+++ b/litellm/vector_stores/utils.py
@@ -1,5 +1,6 @@
from typing import Any, Dict, cast, get_type_hints
+from litellm.llms.base_llm.vector_store.transformation import BaseVectorStoreConfig
from litellm.types.vector_stores import (
VectorStoreCreateOptionalRequestParams,
VectorStoreSearchOptionalRequestParams,
@@ -12,6 +13,7 @@ class VectorStoreRequestUtils:
@staticmethod
def get_requested_vector_store_search_optional_param(
params: Dict[str, Any],
+ vector_store_provider_config: BaseVectorStoreConfig,
) -> VectorStoreSearchOptionalRequestParams:
"""
Filter parameters to only include those defined in VectorStoreSearchOptionalRequestParams.
@@ -27,7 +29,13 @@ def get_requested_vector_store_search_optional_param(
k: v for k, v in params.items() if k in valid_keys and v is not None
}
- return cast(VectorStoreSearchOptionalRequestParams, filtered_params)
+ optional_params = vector_store_provider_config.map_openai_params(
+ non_default_params=params,
+ optional_params=filtered_params,
+ drop_params=False,
+ )
+
+ return cast(VectorStoreSearchOptionalRequestParams, optional_params)
@staticmethod
def get_requested_vector_store_create_optional_param(
@@ -48,4 +56,3 @@ def get_requested_vector_store_create_optional_param(
}
return cast(VectorStoreCreateOptionalRequestParams, filtered_params)
-