Skip to content
Merged
2 changes: 2 additions & 0 deletions litellm/llms/azure_ai/vector_stores/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
from litellm.router import Router

LiteLLMLoggingObj = _LiteLLMLoggingObj
else:
Expand Down Expand Up @@ -115,6 +116,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: dict[str, Any] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict[str, Any]]:
"""
Transform search request for Azure AI Search API
Expand Down
5 changes: 5 additions & 0 deletions litellm/llms/base_llm/vector_store/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
from litellm.router import Router

from ..chat.transformation import BaseLLMException as _BaseLLMException

Expand Down Expand Up @@ -57,6 +58,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: dict[str, Any] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict]:
pass

Expand All @@ -69,6 +71,7 @@ async def atransform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: dict[str, Any] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict]:
"""
Optional async version of transform_search_vector_store_request.
Expand All @@ -84,6 +87,7 @@ async def atransform_search_vector_store_request(
litellm_logging_obj=litellm_logging_obj,
litellm_params=litellm_params,
extra_body=extra_body,
router=router,
)

@abstractmethod
Expand Down Expand Up @@ -197,6 +201,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: Mapping[str, object],
extra_body: Mapping[str, object] | None = None,
router: "Router | None" = None,
) -> NoReturn:
raise NotImplementedError("Direct vector store providers execute the search themselves; no HTTP request shape")

Expand Down
2 changes: 2 additions & 0 deletions litellm/llms/bedrock/vector_stores/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.router import Router
else:
LiteLLMLoggingObj = Any

Expand Down Expand Up @@ -196,6 +197,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: dict[str, Any] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict]:
if isinstance(query, list):
query = " ".join(query)
Expand Down
11 changes: 9 additions & 2 deletions litellm/llms/custom_httpx/llm_http_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ def _rust_responses_websocket_enabled(
AnthropicMessagesStreamingResponse,
)
from litellm.llms.base_llm.passthrough.transformation import BasePassthroughConfig
from litellm.router import Router
from litellm.types.llms.openai_evals import (
CancelEvalResponse,
CancelRunResponse,
Expand Down Expand Up @@ -2923,7 +2924,7 @@ async def async_response_api_handler(
final_response: Final = await self._call_agentic_completion_hooks(
response=initial_response,
model=model,
messages=(input if isinstance(input, list) else [{"role": "user", "content": input}]),
messages=(input if isinstance(input, list) else [{"role": "user", "content": input}]), # pyright: ignore[reportArgumentType] # pre-existing mismatch surfaced by the Router import; the hook accepts response input items at runtime
anthropic_messages_provider_config=responses_api_provider_config,
anthropic_messages_optional_request_params=response_api_optional_request_params,
logging_obj=logging_obj,
Expand Down Expand Up @@ -5415,7 +5416,7 @@ async def _execute_responses_agentic_plan(
try:
response: ResponsesAPIResponse | BaseResponsesAPIStreamingIterator = await litellm.aresponses(
model=patch.model or model,
input=patch.messages,
input=patch.messages, # pyright: ignore[reportArgumentType] # pre-existing mismatch surfaced by the Router import; patch messages are valid response input at runtime
**optional_params,
**kwargs_for_followup,
)
Expand Down Expand Up @@ -9688,6 +9689,7 @@ async def async_vector_store_search_handler(
timeout: float | httpx.Timeout | None = None,
client: HTTPHandler | AsyncHTTPHandler | None = None,
_is_async: bool = False,
router: "Router | None" = None,
) -> VectorStoreSearchResponse:
if isinstance(vector_store_provider_config, BaseDirectVectorStoreConfig):
self._pre_call_direct_vector_store_search(
Expand Down Expand Up @@ -9738,6 +9740,7 @@ async def async_vector_store_search_handler(
litellm_logging_obj=logging_obj,
litellm_params=dict(litellm_params),
extra_body=extra_body,
router=router,
)
else:
(
Expand All @@ -9751,6 +9754,7 @@ async def async_vector_store_search_handler(
litellm_logging_obj=logging_obj,
litellm_params=dict(litellm_params),
extra_body=extra_body,
router=router,
)
all_optional_params: Final[dict[str, object]] = dict(litellm_params)
all_optional_params.update(vector_store_search_optional_params or {})
Expand Down Expand Up @@ -9802,6 +9806,7 @@ def vector_store_search_handler(
timeout: float | httpx.Timeout | None = None,
client: HTTPHandler | AsyncHTTPHandler | None = None,
_is_async: bool = False,
router: "Router | None" = None,
) -> VectorStoreSearchResponse | Coroutine[object, object, VectorStoreSearchResponse]:
if _is_async:
return self.async_vector_store_search_handler(
Expand All @@ -9816,6 +9821,7 @@ def vector_store_search_handler(
extra_body=extra_body,
timeout=timeout,
client=client,
router=router,
)

if isinstance(vector_store_provider_config, BaseDirectVectorStoreConfig):
Expand Down Expand Up @@ -9862,6 +9868,7 @@ def vector_store_search_handler(
litellm_logging_obj=logging_obj,
litellm_params=dict(litellm_params),
extra_body=extra_body,
router=router,
)

all_optional_params: Final[dict[str, object]] = dict(litellm_params)
Expand Down
2 changes: 2 additions & 0 deletions litellm/llms/gemini/vector_stores/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.router import Router
else:
LiteLLMLoggingObj = Any

Expand Down Expand Up @@ -168,6 +169,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: Mapping[str, object] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict]:
"""
Transform search request to Gemini's generateContent format.
Expand Down
2 changes: 2 additions & 0 deletions litellm/llms/milvus/vector_stores/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
from litellm.router import Router

LiteLLMLoggingObj = _LiteLLMLoggingObj
else:
Expand Down Expand Up @@ -123,6 +124,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: dict[str, Any] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict[str, Any]]:
"""
Transform search request for Azure AI Search API
Expand Down
2 changes: 2 additions & 0 deletions litellm/llms/openai/vector_stores/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
from litellm.router import Router

LiteLLMLoggingObj = _LiteLLMLoggingObj
else:
Expand Down Expand Up @@ -99,6 +100,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: dict[str, Any] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict]:
encoded_vector_store_id: Final = encode_url_path_segment(vector_store_id, field_name="vector_store_id")
url: Final = f"{api_base}/{encoded_vector_store_id}/search"
Expand Down
2 changes: 2 additions & 0 deletions litellm/llms/pg_vector/vector_stores/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.router import Router
else:
LiteLLMLoggingObj = Any

Expand Down Expand Up @@ -80,6 +81,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: dict[str, Any] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict]:
encoded_vector_store_id: Final = encode_url_path_segment(vector_store_id, field_name="vector_store_id")
url: Final = f"{api_base}/{encoded_vector_store_id}/search"
Expand Down
2 changes: 2 additions & 0 deletions litellm/llms/ragflow/vector_stores/transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.router import Router
else:
LiteLLMLoggingObj = Any

Expand Down Expand Up @@ -92,6 +93,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: dict[str, Any] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict]:
"""RAGFlow vector stores are management-only, search is not supported."""
raise NotImplementedError("RAGFlow vector stores support dataset management only, not search/retrieval")
Expand Down
38 changes: 30 additions & 8 deletions litellm/llms/s3_vectors/vector_stores/transformation.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import re
from typing import TYPE_CHECKING, Any, Final

import httpx

from litellm.caching._embedding_router import resolve_embedding_router
from litellm.llms.base_llm.vector_store.transformation import BaseVectorStoreConfig
from litellm.llms.bedrock.base_aws_llm import BaseAWSLLM
from litellm.types.router import GenericLiteLLMParams
Expand All @@ -18,6 +18,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
from litellm.router import Router
else:
LiteLLMLoggingObj = Any

Expand Down Expand Up @@ -58,13 +59,20 @@ def validate_environment(self, headers: dict, litellm_params: GenericLiteLLMPara
return headers

def get_complete_url(self, api_base: str | None, litellm_params: dict) -> str:
aws_region_name: Final = litellm_params.get("aws_region_name")
if not aws_region_name:
raise ValueError("aws_region_name is required for S3 Vectors")
if not re.match(r"^[a-z][a-z0-9-]*$", aws_region_name):
raise ValueError("Invalid aws_region_name format")
# Resolve region the same way the ingestion path does:
# dynamic param -> AWS_REGION_NAME -> AWS_REGION -> default (us-west-2)
aws_region_name: Final = self.get_aws_region_name_for_non_llm_api_calls(litellm_params.get("aws_region_name"))
return f"https://s3vectors.{aws_region_name}.api.aws"

def _resolve_query_embedding_router(self, embedding_model: str, router: "Router | None") -> "Router | None":
"""Return the router iff it serves ``embedding_model`` as a deployment."""
if router is None:
return None
model_list: Final = [
dict(m) for m in (router.get_model_list() or ())
] # mutable-ok: resolve_embedding_router requires list[dict]
return resolve_embedding_router(embedding_model=embedding_model, llm_router=router, llm_model_list=model_list)

def transform_search_vector_store_request(
self,
vector_store_id: str,
Expand All @@ -74,6 +82,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: dict[str, Any] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict]:
"""Sync version - generates embedding synchronously."""
# For S3 Vectors, vector_store_id should be in format: bucket_name:index_name
Expand All @@ -99,10 +108,16 @@ def transform_search_vector_store_request(

# Generate embedding for the query
embedding_model: Final = litellm_params.get("embedding_model", "text-embedding-3-small")
embedding_router: Final = self._resolve_query_embedding_router(embedding_model=embedding_model, router=router)

import litellm as litellm_module

embedding_response: Final = litellm_module.embedding(model=embedding_model, input=[query])
embedding_input: Final = [query] # mutable-ok: the embedding API takes list input
embedding_response: Final = (
embedding_router.embedding(model=embedding_model, input=embedding_input)
if embedding_router is not None
else litellm_module.embedding(model=embedding_model, input=embedding_input)
)
query_embedding: Final = embedding_response.data[0]["embedding"]

url: Final = f"{api_base}/QueryVectors"
Expand All @@ -128,6 +143,7 @@ async def atransform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: dict[str, Any] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict]:
"""Async version - generates embedding asynchronously."""
# For S3 Vectors, vector_store_id should be in format: bucket_name:index_name
Expand All @@ -153,10 +169,16 @@ async def atransform_search_vector_store_request(

# Generate embedding for the query asynchronously
embedding_model: Final = litellm_params.get("embedding_model", "text-embedding-3-small")
embedding_router: Final = self._resolve_query_embedding_router(embedding_model=embedding_model, router=router)

import litellm as litellm_module

embedding_response: Final = await litellm_module.aembedding(model=embedding_model, input=[query])
embedding_input: Final = [query] # mutable-ok: the embedding API takes list input
embedding_response: Final = (
await embedding_router.aembedding(model=embedding_model, input=embedding_input)
Comment thread
veria-ai[bot] marked this conversation as resolved.
if embedding_router is not None
else await litellm_module.aembedding(model=embedding_model, input=embedding_input)
)
query_embedding: Final = embedding_response.data[0]["embedding"]

url: Final = f"{api_base}/QueryVectors"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
from litellm.router import Router

LiteLLMLoggingObj = _LiteLLMLoggingObj
else:
Expand Down Expand Up @@ -161,6 +162,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: Mapping[str, object] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict[str, object]]:
"""
Transform search request for Vertex AI RAG API
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

if TYPE_CHECKING:
from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
from litellm.router import Router

LiteLLMLoggingObj = _LiteLLMLoggingObj
else:
Expand Down Expand Up @@ -245,6 +246,7 @@ def transform_search_vector_store_request(
litellm_logging_obj: LiteLLMLoggingObj,
litellm_params: dict,
extra_body: Mapping[str, object] | None = None,
router: "Router | None" = None,
) -> tuple[str, dict[str, object]]:
"""
Transform a search request for the Vertex AI Search (Discovery Engine) API.
Expand Down
Loading
Loading