diff --git a/docs/my-website/docs/providers/azure_ai_vector_stores.md b/docs/my-website/docs/providers/azure_ai_vector_stores.md
new file mode 100644
index 00000000000..d3abb78bbe4
--- /dev/null
+++ b/docs/my-website/docs/providers/azure_ai_vector_stores.md
@@ -0,0 +1,245 @@
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+# Azure AI Search - Vector Store
+
+Use Azure AI Search as a vector store for RAG.
+
+## Quick Start
+
+You need three things:
+1. An Azure AI Search service
+2. An embedding model (to convert your queries to vectors)
+3. A search index with vector fields
+
+## Usage
+
+
+
+
+### Basic Search
+
+```python
+from litellm import vector_stores
+import os
+
+# Set your credentials
+os.environ["AZURE_SEARCH_API_KEY"] = "your-search-api-key"
+os.environ["AZURE_AI_SEARCH_EMBEDDING_API_BASE"] = "your-embedding-endpoint"
+os.environ["AZURE_AI_SEARCH_EMBEDDING_API_KEY"] = "your-embedding-api-key"
+
+# Search the vector store
+response = vector_stores.search(
+ vector_store_id="my-vector-index", # Your Azure AI Search index name
+ query="What is the capital of France?",
+ custom_llm_provider="azure_ai",
+ azure_search_service_name="your-search-service",
+ litellm_embedding_model="azure/text-embedding-3-large",
+ litellm_embedding_config={
+ "api_base": os.getenv("AZURE_AI_SEARCH_EMBEDDING_API_BASE"),
+ "api_key": os.getenv("AZURE_AI_SEARCH_EMBEDDING_API_KEY"),
+ },
+ api_key=os.getenv("AZURE_SEARCH_API_KEY"),
+)
+
+print(response)
+```
+
+### Async Search
+
+```python
+from litellm import vector_stores
+
+response = await vector_stores.asearch(
+ vector_store_id="my-vector-index",
+ query="What is the capital of France?",
+ custom_llm_provider="azure_ai",
+ azure_search_service_name="your-search-service",
+ litellm_embedding_model="azure/text-embedding-3-large",
+ litellm_embedding_config={
+ "api_base": os.getenv("AZURE_AI_SEARCH_EMBEDDING_API_BASE"),
+ "api_key": os.getenv("AZURE_AI_SEARCH_EMBEDDING_API_KEY"),
+ },
+ api_key=os.getenv("AZURE_SEARCH_API_KEY"),
+)
+
+print(response)
+```
+
+### Advanced Options
+
+```python
+from litellm import vector_stores
+
+response = vector_stores.search(
+ vector_store_id="my-vector-index",
+ query="What is the capital of France?",
+ custom_llm_provider="azure_ai",
+ azure_search_service_name="your-search-service",
+ litellm_embedding_model="azure/text-embedding-3-large",
+ litellm_embedding_config={
+ "api_base": os.getenv("AZURE_AI_SEARCH_EMBEDDING_API_BASE"),
+ "api_key": os.getenv("AZURE_AI_SEARCH_EMBEDDING_API_KEY"),
+ },
+ api_key=os.getenv("AZURE_SEARCH_API_KEY"),
+ top_k=10, # Number of results to return
+ azure_search_vector_field="contentVector", # Custom vector field name
+)
+
+print(response)
+```
+
+
+
+
+
+### Setup Config
+
+Add this to your config.yaml:
+
+```yaml
+vector_store_registry:
+ - vector_store_name: "azure-ai-search-litellm-website-knowledgebase"
+ litellm_params:
+ vector_store_id: "test-litellm-app_1761094730750"
+ custom_llm_provider: "azure_ai"
+ api_key: os.environ/AZURE_SEARCH_API_KEY
+ litellm_embedding_model: "azure/text-embedding-3-large"
+ litellm_embedding_config:
+ api_base: https://krris-mh44uf7y-eastus2.cognitiveservices.azure.com/
+ api_key: os.environ/AZURE_API_KEY
+ api_version: "2025-09-01"
+```
+
+### Start Proxy
+
+```bash
+litellm --config /path/to/config.yaml
+```
+
+### Search via API
+
+```bash
+curl -X POST 'http://0.0.0.0:4000/v1/vector_stores/my-vector-index/search' \
+-H 'Content-Type: application/json' \
+-H 'Authorization: Bearer sk-1234' \
+-d '{
+ "query": "What is the capital of France?",
+}'
+```
+
+
+
+
+## Required Parameters
+
+| Parameter | Type | Description |
+|-----------|------|-------------|
+| `vector_store_id` | string | Your Azure AI Search index name |
+| `custom_llm_provider` | string | Set to `"azure_ai"` |
+| `azure_search_service_name` | string | Name of your Azure AI Search service |
+| `litellm_embedding_model` | string | Model to generate query embeddings (e.g., `"azure/text-embedding-3-large"`) |
+| `litellm_embedding_config` | dict | Config for the embedding model (api_base, api_key, api_version) |
+| `api_key` | string | Your Azure AI Search API key |
+
+## Supported Features
+
+| Feature | Status | Notes |
+|---------|--------|-------|
+| Logging | ✅ Supported | Full logging support available |
+| Guardrails | ❌ Not Yet Supported | Guardrails are not currently supported for vector stores |
+| Cost Tracking | ✅ Supported | Cost is $0 according to Azure |
+| Unified API | ✅ Supported | Call via OpenAI compatible `/v1/vector_stores/search` endpoint |
+| Passthrough | ❌ Not yet supported | |
+
+## Response Format
+
+The response follows the standard LiteLLM vector store format:
+
+```json
+{
+ "object": "vector_store.search_results.page",
+ "search_query": "What is the capital of France?",
+ "data": [
+ {
+ "score": 0.95,
+ "content": [
+ {
+ "text": "Paris is the capital of France...",
+ "type": "text"
+ }
+ ],
+ "file_id": "doc_123",
+ "filename": "Document doc_123",
+ "attributes": {
+ "document_id": "doc_123"
+ }
+ }
+ ]
+}
+```
+
+## How It Works
+
+When you search:
+
+1. LiteLLM converts your query to a vector using the embedding model you specified
+2. It sends the vector to Azure AI Search
+3. Azure AI Search finds the most similar documents in your index
+4. Results come back with similarity scores
+
+The embedding model can be any model supported by LiteLLM - Azure OpenAI, OpenAI, Bedrock, etc.
+
+## Setting Up Your Azure AI Search Index
+
+Your index needs a vector field. Here's what that looks like:
+
+```json
+{
+ "name": "my-vector-index",
+ "fields": [
+ {
+ "name": "id",
+ "type": "Edm.String",
+ "key": true
+ },
+ {
+ "name": "content",
+ "type": "Edm.String"
+ },
+ {
+ "name": "contentVector",
+ "type": "Collection(Edm.Single)",
+ "searchable": true,
+ "dimensions": 1536,
+ "vectorSearchProfile": "myVectorProfile"
+ }
+ ]
+}
+```
+
+The vector dimensions must match your embedding model. For example:
+- `text-embedding-3-large`: 1536 dimensions
+- `text-embedding-3-small`: 1536 dimensions
+- `text-embedding-ada-002`: 1536 dimensions
+
+
+## Common Issues
+
+**"Failed to generate embedding for query"**
+
+Your embedding model config is wrong. Check:
+- `litellm_embedding_config` has the right api_base and api_key
+- The embedding model name is correct
+- Your credentials work
+
+**"Index not found"**
+
+The `vector_store_id` doesn't match any index in your search service. Check:
+- The index name is correct
+- You're using the right search service name
+
+**"Field 'contentVector' not found"**
+
+Your index uses a different vector field name. Pass it via `azure_search_vector_field`.
+
diff --git a/docs/my-website/docs/vector_stores/create.md b/docs/my-website/docs/vector_stores/create.md
index f9bdcb9b34c..c97f88a2543 100644
--- a/docs/my-website/docs/vector_stores/create.md
+++ b/docs/my-website/docs/vector_stores/create.md
@@ -12,7 +12,7 @@ Create a vector store which can be used to store and search document chunks for
| Cost Tracking | ✅ | Tracked per vector store operation |
| Logging | ✅ | Works across all integrations |
| End-user Tracking | ✅ | |
-| Support LLM Providers | **OpenAI, Azure OpenAI, Bedrock, Vertex RAG Engine** | Full vector stores API support across providers |
+| Support LLM Providers | **OpenAI** | Full vector stores API support across providers |
## Usage
@@ -21,7 +21,7 @@ Create a vector store which can be used to store and search document chunks for
-#### Non-streaming example
+#### Async example
```python showLineNumbers title="Create Vector Store - Basic"
import litellm
@@ -32,7 +32,7 @@ response = await litellm.vector_stores.acreate(
print(response)
```
-#### Synchronous example
+#### Sync example
```python showLineNumbers title="Create Vector Store - Sync"
import litellm
diff --git a/docs/my-website/docs/vector_stores/search.md b/docs/my-website/docs/vector_stores/search.md
index 5c3d02be3da..5d0a2b737b9 100644
--- a/docs/my-website/docs/vector_stores/search.md
+++ b/docs/my-website/docs/vector_stores/search.md
@@ -12,7 +12,7 @@ Search a vector store for relevant chunks based on a query and file attributes f
| Cost Tracking | ✅ | Tracked per search operation |
| Logging | ✅ | Works across all integrations |
| End-user Tracking | ✅ | |
-| Support LLM Providers | **OpenAI, Azure OpenAI, Bedrock, Vertex RAG Engine** | Full vector stores API support across providers |
+| Support LLM Providers | **OpenAI, Azure OpenAI, Bedrock, Vertex RAG Engine, Azure AI** | Full vector stores API support across providers |
## Usage
@@ -105,6 +105,35 @@ response = await litellm.vector_stores.asearch(
print(response)
```
+
+
+
+
+#### Using Azure AI Search
+```python showLineNumbers title="Search Vector Store - Azure AI Provider"
+import litellm
+import os
+
+# Set credentials
+os.environ["AZURE_SEARCH_API_KEY"] = "your-search-api-key"
+
+response = await litellm.vector_stores.asearch(
+ vector_store_id="my-vector-index",
+ query="What is the capital of France?",
+ custom_llm_provider="azure_ai",
+ azure_search_service_name="your-search-service",
+ litellm_embedding_model="azure/text-embedding-3-large",
+ litellm_embedding_config={
+ "api_base": "your-embedding-endpoint",
+ "api_key": "your-embedding-api-key",
+ },
+ api_key=os.getenv("AZURE_SEARCH_API_KEY"),
+)
+print(response)
+```
+
+[See full Azure AI vector store documentation](../providers/azure_ai_vector_stores.md)
+
diff --git a/docs/my-website/sidebars.js b/docs/my-website/sidebars.js
index 2dcc5b48b28..6811aeada1d 100644
--- a/docs/my-website/sidebars.js
+++ b/docs/my-website/sidebars.js
@@ -400,6 +400,7 @@ const sidebars = {
type: "category",
label: "/vector_stores",
items: [
+ "vector_stores/create",
"vector_stores/search",
]
},
@@ -450,6 +451,7 @@ const sidebars = {
"providers/azure_ocr",
"providers/azure_ai_speech",
"providers/azure_ai_img",
+ "providers/azure_ai_vector_stores",
]
},
{
diff --git a/enterprise/litellm_enterprise/proxy/hooks/managed_files.py b/enterprise/litellm_enterprise/proxy/hooks/managed_files.py
index 1dfa746b4f0..c55a4f03898 100644
--- a/enterprise/litellm_enterprise/proxy/hooks/managed_files.py
+++ b/enterprise/litellm_enterprise/proxy/hooks/managed_files.py
@@ -152,7 +152,7 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints):
"status": file_object.status,
},
"update": {}, # don't do anything if it already exists
- }
+ },
)
async def get_unified_file_id(
@@ -224,9 +224,10 @@ class _PROXY_LiteLLMManagedFiles(CustomLogger, BaseFileEndpoints):
where={"unified_object_id": unified_object_id}
)
)
+
if managed_object:
return managed_object.created_by == user_id
- return False
+ return True # don't raise error if managed object is not found
async def get_user_created_file_ids(
self, user_api_key_dict: UserAPIKeyAuth, model_object_ids: List[str]
diff --git a/enterprise/litellm_enterprise/proxy/vector_stores/endpoints.py b/enterprise/litellm_enterprise/proxy/vector_stores/endpoints.py
index bb4b546b8d3..fdb1dba372f 100644
--- a/enterprise/litellm_enterprise/proxy/vector_stores/endpoints.py
+++ b/enterprise/litellm_enterprise/proxy/vector_stores/endpoints.py
@@ -9,6 +9,7 @@ All /vector_store management endpoints
"""
import copy
+import json
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException
@@ -16,7 +17,11 @@ from fastapi import APIRouter, Depends, HTTPException
import litellm
from litellm._logging import verbose_proxy_logger
from litellm.litellm_core_utils.safe_json_dumps import safe_dumps
-from litellm.proxy._types import UserAPIKeyAuth
+from litellm.proxy._types import (
+ LiteLLM_ManagedVectorStoresTable,
+ ResponseLiteLLM_ManagedVectorStore,
+ UserAPIKeyAuth,
+)
from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
from litellm.types.vector_stores import (
LiteLLM_ManagedVectorStore,
@@ -29,6 +34,7 @@ from litellm.vector_stores.vector_store_registry import VectorStoreRegistry
router = APIRouter()
+
########################################################
# Management Endpoints
########################################################
@@ -79,7 +85,9 @@ async def new_vector_store(
litellm_params_json: Optional[str] = None
_input_litellm_params: dict = vector_store.get("litellm_params", {}) or {}
if _input_litellm_params is not None:
- litellm_params_dict = GenericLiteLLMParams(**_input_litellm_params).model_dump(exclude_none=True)
+ litellm_params_dict = GenericLiteLLMParams(
+ **_input_litellm_params
+ ).model_dump(exclude_none=True)
litellm_params_json = safe_dumps(litellm_params_dict)
del vector_store["litellm_params"]
@@ -227,6 +235,7 @@ async def delete_vector_store(
"/vector_store/info",
tags=["vector store management"],
dependencies=[Depends(user_api_key_auth)],
+ response_model=ResponseLiteLLM_ManagedVectorStore,
)
async def get_vector_store_info(
data: VectorStoreInfoRequest,
@@ -239,8 +248,39 @@ async def get_vector_store_info(
raise HTTPException(status_code=500, detail="Database not connected")
try:
- vector_store = await prisma_client.db.litellm_managedvectorstorestable.find_unique(
- where={"vector_store_id": data.vector_store_id}
+ if litellm.vector_store_registry is not None:
+ vector_store = litellm.vector_store_registry.get_litellm_managed_vector_store_from_registry(
+ vector_store_id=data.vector_store_id
+ )
+ if vector_store is not None:
+ vector_store_metadata = vector_store.get("vector_store_metadata")
+ # Parse metadata if it's a JSON string
+ parsed_metadata: Optional[dict] = None
+ if isinstance(vector_store_metadata, str):
+ parsed_metadata = json.loads(vector_store_metadata)
+ elif isinstance(vector_store_metadata, dict):
+ parsed_metadata = vector_store_metadata
+
+ vector_store_pydantic_obj = LiteLLM_ManagedVectorStoresTable(
+ vector_store_id=vector_store.get("vector_store_id") or "",
+ custom_llm_provider=vector_store.get("custom_llm_provider") or "",
+ vector_store_name=vector_store.get("vector_store_name") or None,
+ vector_store_description=vector_store.get(
+ "vector_store_description"
+ )
+ or None,
+ vector_store_metadata=parsed_metadata,
+ created_at=vector_store.get("created_at") or None,
+ updated_at=vector_store.get("updated_at") or None,
+ litellm_credential_name=vector_store.get("litellm_credential_name"),
+ litellm_params=vector_store.get("litellm_params") or None,
+ )
+ return {"vector_store": vector_store_pydantic_obj}
+
+ vector_store = (
+ await prisma_client.db.litellm_managedvectorstorestable.find_unique(
+ where={"vector_store_id": data.vector_store_id}
+ )
)
if vector_store is None:
raise HTTPException(
@@ -248,7 +288,7 @@ async def get_vector_store_info(
detail=f"Vector store with ID {data.vector_store_id} not found",
)
- vector_store_dict = vector_store.model_dump()
+ vector_store_dict = vector_store.model_dump() # type: ignore[attr-defined]
return {"vector_store": vector_store_dict}
except Exception as e:
verbose_proxy_logger.exception(f"Error getting vector store info: {str(e)}")
@@ -274,7 +314,9 @@ async def update_vector_store(
update_data = data.model_dump(exclude_unset=True)
vector_store_id = update_data.pop("vector_store_id")
if update_data.get("vector_store_metadata") is not None:
- update_data["vector_store_metadata"] = safe_dumps(update_data["vector_store_metadata"])
+ update_data["vector_store_metadata"] = safe_dumps(
+ update_data["vector_store_metadata"]
+ )
updated = await prisma_client.db.litellm_managedvectorstorestable.update(
where={"vector_store_id": vector_store_id},
diff --git a/litellm/llms/azure_ai/vector_stores/__init__.py b/litellm/llms/azure_ai/vector_stores/__init__.py
new file mode 100644
index 00000000000..74ffe1afb17
--- /dev/null
+++ b/litellm/llms/azure_ai/vector_stores/__init__.py
@@ -0,0 +1,4 @@
+from litellm.llms.azure_ai.vector_stores.transformation import AzureAIVectorStoreConfig
+
+__all__ = ["AzureAIVectorStoreConfig"]
+
diff --git a/litellm/llms/azure_ai/vector_stores/transformation.py b/litellm/llms/azure_ai/vector_stores/transformation.py
new file mode 100644
index 00000000000..f99d2c4c4b2
--- /dev/null
+++ b/litellm/llms/azure_ai/vector_stores/transformation.py
@@ -0,0 +1,237 @@
+from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
+
+import httpx
+
+import litellm
+from litellm.llms.azure.common_utils import BaseAzureLLM
+from litellm.llms.base_llm.vector_store.transformation import BaseVectorStoreConfig
+from litellm.types.router import GenericLiteLLMParams
+from litellm.types.vector_stores import (
+ VectorStoreCreateOptionalRequestParams,
+ VectorStoreCreateResponse,
+ VectorStoreResultContent,
+ VectorStoreSearchOptionalRequestParams,
+ VectorStoreSearchResponse,
+ VectorStoreSearchResult,
+)
+
+if TYPE_CHECKING:
+ from litellm.litellm_core_utils.litellm_logging import Logging as _LiteLLMLoggingObj
+
+ LiteLLMLoggingObj = _LiteLLMLoggingObj
+else:
+ LiteLLMLoggingObj = Any
+
+
+class AzureAIVectorStoreConfig(BaseVectorStoreConfig, BaseAzureLLM):
+ """
+ Configuration for Azure AI Search Vector Store
+
+ This implementation uses the Azure AI Search API for vector store operations.
+ Supports vector search with embeddings generated via litellm.embeddings.
+ """
+
+ def __init__(self):
+ super().__init__()
+
+ def validate_environment(
+ self, headers: dict, litellm_params: Optional[GenericLiteLLMParams]
+ ) -> dict:
+
+ basic_headers = self._base_validate_azure_environment(headers, litellm_params)
+ basic_headers.update({"Content-Type": "application/json"})
+ return basic_headers
+
+ def get_complete_url(
+ self,
+ api_base: Optional[str],
+ litellm_params: dict,
+ ) -> str:
+ """
+ Get the base endpoint for Azure AI Search API
+
+ Expected format: https://{search_service_name}.search.windows.net
+ """
+ if api_base:
+ return api_base.rstrip("/")
+
+ # Get search service name from litellm_params
+ search_service_name = litellm_params.get("azure_search_service_name")
+
+ if not search_service_name:
+ raise ValueError(
+ "Azure AI Search service name is required. "
+ "Provide it via litellm_params['azure_search_service_name'] or api_base parameter"
+ )
+
+ # Azure AI Search endpoint
+ return f"https://{search_service_name}.search.windows.net"
+
+ def transform_search_vector_store_request(
+ self,
+ vector_store_id: str,
+ query: Union[str, List[str]],
+ vector_store_search_optional_params: VectorStoreSearchOptionalRequestParams,
+ api_base: str,
+ litellm_logging_obj: LiteLLMLoggingObj,
+ litellm_params: dict,
+ ) -> Tuple[str, Dict[str, Any]]:
+ """
+ Transform search request for Azure AI Search API
+
+ Generates embeddings using litellm.embeddings and constructs Azure AI Search request
+ """
+ # Convert query to string if it's a list
+ if isinstance(query, list):
+ query = " ".join(query)
+
+ # Get embedding model from litellm_params (required)
+ embedding_model = litellm_params.get("litellm_embedding_model")
+ if not embedding_model:
+ raise ValueError(
+ "embedding_model is required in litellm_params for Azure AI Search. "
+ "Example: litellm_params['embedding_model'] = 'azure/text-embedding-3-large'"
+ )
+
+ embedding_config = litellm_params.get("litellm_embedding_config", {})
+ if not embedding_config:
+ raise ValueError(
+ "embedding_config is required in litellm_params for Azure AI Search. "
+ "Example: litellm_params['embedding_config'] = {'api_base': 'https://krris-mh44uf7y-eastus2.cognitiveservices.azure.com/', 'api_key': 'os.environ/AZURE_API_KEY', 'api_version': '2025-09-01'}"
+ )
+
+ # Get vector field name (defaults to contentVector)
+ vector_field = litellm_params.get("azure_search_vector_field", "contentVector")
+
+ # Get top_k (number of results to return)
+ top_k = vector_store_search_optional_params.get("top_k", 10)
+
+ # Generate embedding for the query using litellm.embeddings
+ try:
+ embedding_response = litellm.embedding(
+ model=embedding_model,
+ input=[query],
+ **embedding_config,
+ )
+ query_vector = embedding_response.data[0]["embedding"]
+ except Exception as e:
+ raise Exception(f"Failed to generate embedding for query: {str(e)}")
+
+ # Azure AI Search endpoint for search
+ index_name = vector_store_id # vector_store_id is the index name
+ url = f"{api_base}/indexes/{index_name}/docs/search?api-version=2024-07-01"
+
+ # Build the request body for Azure AI Search with vector search
+ request_body = {
+ "search": "*", # Get all documents (filtered by vector similarity)
+ "vectorQueries": [
+ {
+ "vector": query_vector,
+ "fields": vector_field,
+ "kind": "vector",
+ "k": top_k, # Number of nearest neighbors to return
+ }
+ ],
+ "select": "id,content", # Fields to return (customize based on schema)
+ "top": top_k,
+ }
+
+ #########################################################
+ # Update logging object with details of the request
+ #########################################################
+ litellm_logging_obj.model_call_details["input"] = query
+ litellm_logging_obj.model_call_details["embedding_model"] = embedding_model
+ litellm_logging_obj.model_call_details["top_k"] = top_k
+
+ return url, request_body
+
+ def transform_search_vector_store_response(
+ self, response: httpx.Response, litellm_logging_obj: LiteLLMLoggingObj
+ ) -> VectorStoreSearchResponse:
+ """
+ Transform Azure AI Search API response to standard vector store search response
+
+ Handles the format from Azure AI Search which returns:
+ {
+ "value": [
+ {
+ "id": "...",
+ "content": "...",
+ "@search.score": 0.95,
+ ... (other fields)
+ }
+ ]
+ }
+ """
+ try:
+ response_json = response.json()
+
+ # Extract results from Azure AI Search API response
+ results = response_json.get("value", [])
+
+ # Transform results to standard format
+ search_results: List[VectorStoreSearchResult] = []
+ for result in results:
+ # Extract document ID
+ document_id = result.get("id", "")
+
+ # Extract text content
+ text_content = result.get("content", "")
+
+ content = [
+ VectorStoreResultContent(
+ text=text_content,
+ type="text",
+ )
+ ]
+
+ # Get the search score (relevance score from Azure AI Search)
+ score = result.get("@search.score", 0.0)
+
+ # Use document ID as both file_id and filename
+ file_id = document_id
+ filename = f"Document {document_id}"
+
+ # Build attributes with all available metadata
+ # Exclude system fields and already-processed fields
+ attributes = {}
+ for key, value in result.items():
+ if key not in ["id", "content", "contentVector", "@search.score"]:
+ attributes[key] = value
+
+ # Always include document_id in attributes
+ attributes["document_id"] = document_id
+
+ result_obj = VectorStoreSearchResult(
+ score=score,
+ content=content,
+ file_id=file_id,
+ filename=filename,
+ attributes=attributes,
+ )
+ search_results.append(result_obj)
+
+ return VectorStoreSearchResponse(
+ object="vector_store.search_results.page",
+ search_query=litellm_logging_obj.model_call_details.get("input", ""),
+ data=search_results,
+ )
+
+ except Exception as e:
+ raise self.get_error_class(
+ error_message=str(e),
+ status_code=response.status_code,
+ headers=response.headers,
+ )
+
+ def transform_create_vector_store_request(
+ self,
+ vector_store_create_optional_params: VectorStoreCreateOptionalRequestParams,
+ api_base: str,
+ ) -> Tuple[str, Dict]:
+ raise NotImplementedError
+
+ def transform_create_vector_store_response(
+ self, response: httpx.Response
+ ) -> VectorStoreCreateResponse:
+ raise NotImplementedError
diff --git a/litellm/proxy/_new_secret_config.yaml b/litellm/proxy/_new_secret_config.yaml
index 7725446d10c..0ee11fdb3f4 100644
--- a/litellm/proxy/_new_secret_config.yaml
+++ b/litellm/proxy/_new_secret_config.yaml
@@ -2,35 +2,20 @@ model_list:
- model_name: bedrock-anthropic-claude-sonnet-4-5-20250929-v1
litellm_params:
model: bedrock/global.anthropic.claude-sonnet-4-5-20250929-v1:0
+ - model_name: embedding-model
+ 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"
vector_store_registry:
- - vector_store_name: "vertex-ai-litellm-website-knowledgebase"
+ - vector_store_name: "azure-ai-search-litellm-website-knowledgebase"
litellm_params:
vector_store_id: "test-litellm-app_1761094730750"
- custom_llm_provider: "vertex_ai/search_api"
- vertex_project: "test-litellm-app"
- vertex_location: "us-central1"
- vector_store_description: "Vertex AI vector store for the Litellm website knowledgebase"
- vector_store_metadata:
- source: "https://www.litellm.com/docs"
-mcp_servers:
- github_mcp:
- url: "https://api.githubcopilot.com/mcp"
- auth_type: oauth2
- authorization_url: https://github.com/login/oauth/authorize
- token_url: https://github.com/login/oauth/access_token
- client_id: os.environ/GITHUB_OAUTH_CLIENT_ID
- client_secret: os.environ/GITHUB_OAUTH_CLIENT_SECRET
- scopes: ["public_repo", "user:email"]
-
-general_settings:
- pass_through_endpoints:
- - path: "/fake-openai-proxy-10" # Route on LiteLLM Proxy
- target: "https://webhook.site/74bbcc59-a61f-4028-81e2-9e06814e81fe" # Target endpoint
- headers: # Headers to forward
- Authorization: "bearer sk-1234"
- content-type: application/json
- accept: application/json
- auth: true
- include_subpath: true
- cost_per_request: 0
+ custom_llm_provider: "azure_ai"
+ litellm_embedding_model: "azure/text-embedding-3-large"
+ litellm_embedding_config:
+ api_base: https://krris-mh44uf7y-eastus2.cognitiveservices.azure.com/
+ api_key: os.environ/AZURE_API_KEY
+ api_version: "2025-09-01"
\ No newline at end of file
diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py
index 36446e65e66..a02e15e0103 100644
--- a/litellm/proxy/_types.py
+++ b/litellm/proxy/_types.py
@@ -323,11 +323,9 @@ class LiteLLMRoutes(enum.Enum):
"/v1/vector_stores",
"/vector_stores/{vector_store_id}/search",
"/v1/vector_stores/{vector_store_id}/search",
-
# search
"/search",
"/v1/search",
-
# OCR
"/ocr",
"/v1/ocr",
@@ -3496,3 +3494,19 @@ class EnterpriseLicenseData(TypedDict, total=False):
allowed_features: List[str]
max_users: int
max_teams: int
+
+
+class LiteLLM_ManagedVectorStoresTable(LiteLLMPydanticObjectBase):
+ vector_store_id: str
+ custom_llm_provider: str
+ vector_store_name: Optional[str]
+ vector_store_description: Optional[str]
+ vector_store_metadata: Optional[Dict[str, Any]]
+ created_at: Optional[datetime]
+ updated_at: Optional[datetime]
+ litellm_credential_name: Optional[str]
+ litellm_params: Optional[Dict[str, Any]]
+
+
+class ResponseLiteLLM_ManagedVectorStore(TypedDict, total=False):
+ vector_store: LiteLLM_ManagedVectorStoresTable
diff --git a/litellm/utils.py b/litellm/utils.py
index cb712b69684..5ad1553b03f 100644
--- a/litellm/utils.py
+++ b/litellm/utils.py
@@ -3062,26 +3062,24 @@ def _remove_unsupported_params(
def filter_out_litellm_params(kwargs: dict) -> dict:
"""
Filter out LiteLLM internal parameters from kwargs dict.
-
- Returns a new dict containing only non-LiteLLM parameters that should be
+
+ Returns a new dict containing only non-LiteLLM parameters that should be
passed to external provider APIs.
-
+
Args:
kwargs: Dictionary that may contain LiteLLM internal parameters
-
+
Returns:
Dictionary with LiteLLM internal parameters filtered out
-
+
Example:
>>> kwargs = {"query": "test", "shared_session": session_obj, "metadata": {}}
>>> filtered = filter_out_litellm_params(kwargs)
>>> # filtered = {"query": "test"}
"""
-
+
return {
- key: value
- for key, value in kwargs.items()
- if key not in all_litellm_params
+ key: value for key, value in kwargs.items() if key not in all_litellm_params
}
@@ -7536,6 +7534,12 @@ class ProviderConfigManager:
)
return PGVectorStoreConfig()
+ elif litellm.LlmProviders.AZURE_AI == provider:
+ from litellm.llms.azure_ai.vector_stores.transformation import (
+ AzureAIVectorStoreConfig,
+ )
+
+ return AzureAIVectorStoreConfig()
return None
@staticmethod
@@ -7689,15 +7693,9 @@ class ProviderConfigManager:
"""
Get Search configuration for a given provider.
"""
- from litellm.llms.dataforseo.search.transformation import (
- DataForSEOSearchConfig,
- )
- from litellm.llms.exa_ai.search.transformation import (
- ExaAISearchConfig,
- )
- from litellm.llms.google_pse.search.transformation import (
- GooglePSESearchConfig,
- )
+ from litellm.llms.dataforseo.search.transformation import DataForSEOSearchConfig
+ from litellm.llms.exa_ai.search.transformation import ExaAISearchConfig
+ from litellm.llms.google_pse.search.transformation import GooglePSESearchConfig
from litellm.llms.parallel_ai.search.transformation import (
ParallelAISearchConfig,
)
diff --git a/litellm/vector_stores/main.py b/litellm/vector_stores/main.py
index 3cbbfea1804..2e121615297 100644
--- a/litellm/vector_stores/main.py
+++ b/litellm/vector_stores/main.py
@@ -287,6 +287,7 @@ async def asearch(
Async: Search a vector store for relevant chunks based on a query and file attributes filter.
"""
local_vars = locals()
+
try:
loop = asyncio.get_event_loop()
kwargs["asearch"] = True
diff --git a/tests/vector_store_tests/test_azure_ai_vector_store.py b/tests/vector_store_tests/test_azure_ai_vector_store.py
new file mode 100644
index 00000000000..52eb6635a98
--- /dev/null
+++ b/tests/vector_store_tests/test_azure_ai_vector_store.py
@@ -0,0 +1,39 @@
+import pytest
+import litellm
+import json
+import os
+from litellm.vector_stores import (
+ search as vector_store_search,
+ asearch as vector_store_asearch,
+)
+
+
+@pytest.mark.parametrize("sync_mode", [True, False])
+@pytest.mark.asyncio
+async def test_basic_search_vector_store(sync_mode):
+ litellm._turn_on_debug()
+ litellm.set_verbose = True
+ base_request_args = {
+ "vector_store_id": "my-vector-index",
+ "custom_llm_provider": "azure_ai",
+ "azure_search_service_name": "azure-kb-search",
+ "litellm_embedding_model": "azure/text-embedding-3-large",
+ "litellm_embedding_config": {
+ "api_base": os.getenv("AZURE_AI_SEARCH_EMBEDDING_API_BASE"),
+ "api_key": os.getenv("AZURE_AI_SEARCH_EMBEDDING_API_KEY"),
+ },
+ "api_key": os.getenv("AZURE_SEARCH_API_KEY"),
+ }
+ default_query = base_request_args.pop("query", "Basic ping")
+ print(f"base_request_args: {base_request_args}")
+ try:
+ if sync_mode:
+ response = vector_store_search(query=default_query, **base_request_args)
+ else:
+ response = await vector_store_asearch(
+ query=default_query, **base_request_args
+ )
+ except litellm.InternalServerError:
+ pytest.skip("Skipping test due to litellm.InternalServerError")
+
+ print("litellm response=", json.dumps(response, indent=4, default=str))