Spaces:
Paused
Paused
| import requests | |
| from typing import List, Dict, Any, Optional, Union | |
| from .exceptions import UnauthorizedError, NotFoundError | |
| class ModelsManagementClient: | |
| def __init__(self, base_url: str, api_key: Optional[str] = None): | |
| """ | |
| Initialize the ModelsManagementClient. | |
| Args: | |
| base_url (str): The base URL of the LiteLLM proxy server (e.g., "http://localhost:8000") | |
| api_key (Optional[str]): API key for authentication. If provided, it will be sent as a Bearer token. | |
| """ | |
| self._base_url = base_url.rstrip("/") # Remove trailing slash if present | |
| self._api_key = api_key | |
| def _get_headers(self) -> Dict[str, str]: | |
| """ | |
| Get the headers for API requests, including authorization if api_key is set. | |
| Returns: | |
| Dict[str, str]: Headers to use for API requests | |
| """ | |
| headers = {} | |
| if self._api_key: | |
| headers["Authorization"] = f"Bearer {self._api_key}" | |
| return headers | |
| def list(self, return_request: bool = False) -> Union[List[Dict[str, Any]], requests.Request]: | |
| """ | |
| Get the list of models supported by the server. | |
| Args: | |
| return_request (bool): If True, returns the prepared request object instead of executing it. | |
| Useful for inspection or modification before sending. | |
| Returns: | |
| Union[List[Dict[str, Any]], requests.Request]: Either a list of model information dictionaries | |
| or a prepared request object if return_request is True. | |
| Raises: | |
| UnauthorizedError: If the request fails with a 401 status code | |
| requests.exceptions.RequestException: If the request fails with any other error | |
| """ | |
| url = f"{self._base_url}/models" | |
| request = requests.Request("GET", url, headers=self._get_headers()) | |
| if return_request: | |
| return request | |
| # Prepare and send the request | |
| session = requests.Session() | |
| try: | |
| response = session.send(request.prepare()) | |
| response.raise_for_status() | |
| return response.json()["data"] | |
| except requests.exceptions.HTTPError as e: | |
| if e.response.status_code == 401: | |
| raise UnauthorizedError(e) | |
| raise | |
| def new( | |
| self, | |
| model_name: str, | |
| model_params: Dict[str, Any], | |
| model_info: Optional[Dict[str, Any]] = None, | |
| return_request: bool = False, | |
| ) -> Union[Dict[str, Any], requests.Request]: | |
| """ | |
| Add a new model to the proxy. | |
| Args: | |
| model_name (str): Name of the model to add | |
| model_params (Dict[str, Any]): Parameters for the model (e.g., model type, api_base, api_key) | |
| model_info (Optional[Dict[str, Any]]): Additional information about the model | |
| return_request (bool): If True, returns the prepared request object instead of executing it | |
| Returns: | |
| Union[Dict[str, Any], requests.Request]: Either the response from the server or | |
| a prepared request object if return_request is True | |
| Raises: | |
| UnauthorizedError: If the request fails with a 401 status code | |
| requests.exceptions.RequestException: If the request fails with any other error | |
| """ | |
| url = f"{self._base_url}/model/new" | |
| data = { | |
| "model_name": model_name, | |
| "litellm_params": model_params, | |
| } | |
| if model_info: | |
| data["model_info"] = model_info | |
| request = requests.Request("POST", url, headers=self._get_headers(), json=data) | |
| if return_request: | |
| return request | |
| # Prepare and send the request | |
| session = requests.Session() | |
| try: | |
| response = session.send(request.prepare()) | |
| response.raise_for_status() | |
| return response.json() | |
| except requests.exceptions.HTTPError as e: | |
| if e.response.status_code == 401: | |
| raise UnauthorizedError(e) | |
| raise | |
| def delete(self, model_id: str, return_request: bool = False) -> Union[Dict[str, Any], requests.Request]: | |
| """ | |
| Delete a model from the proxy. | |
| Args: | |
| model_id (str): ID of the model to delete (e.g., "2f23364f-4579-4d79-a43a-2d48dd551c2e") | |
| return_request (bool): If True, returns the prepared request object instead of executing it | |
| Returns: | |
| Union[Dict[str, Any], requests.Request]: Either the response from the server or | |
| a prepared request object if return_request is True | |
| Raises: | |
| UnauthorizedError: If the request fails with a 401 status code | |
| NotFoundError: If the request fails with a 404 status code or indicates the model was not found | |
| requests.exceptions.RequestException: If the request fails with any other error | |
| """ | |
| url = f"{self._base_url}/model/delete" | |
| data = {"id": model_id} | |
| request = requests.Request("POST", url, headers=self._get_headers(), json=data) | |
| if return_request: | |
| return request | |
| # Prepare and send the request | |
| session = requests.Session() | |
| try: | |
| response = session.send(request.prepare()) | |
| response.raise_for_status() | |
| return response.json() | |
| except requests.exceptions.HTTPError as e: | |
| if e.response.status_code == 401: | |
| raise UnauthorizedError(e) | |
| if e.response.status_code == 404 or "not found" in e.response.text.lower(): | |
| raise NotFoundError(e) | |
| raise | |
| def get( | |
| self, model_id: Optional[str] = None, model_name: Optional[str] = None, return_request: bool = False | |
| ) -> Union[Dict[str, Any], requests.Request]: | |
| """ | |
| Get information about a specific model by its ID or name. | |
| Args: | |
| model_id (Optional[str]): ID of the model to retrieve | |
| model_name (Optional[str]): Name of the model to retrieve | |
| return_request (bool): If True, returns the prepared request object instead of executing it | |
| Returns: | |
| Union[Dict[str, Any], requests.Request]: Either the model information from the server or | |
| a prepared request object if return_request is True | |
| Raises: | |
| ValueError: If neither model_id nor model_name is provided, or if both are provided | |
| UnauthorizedError: If the request fails with a 401 status code | |
| NotFoundError: If the model is not found | |
| requests.exceptions.RequestException: If the request fails with any other error | |
| """ | |
| if (model_id is None and model_name is None) or (model_id is not None and model_name is not None): | |
| raise ValueError("Exactly one of model_id or model_name must be provided") | |
| # If return_request is True, delegate to info | |
| if return_request: | |
| result = self.info(return_request=True) | |
| assert isinstance(result, requests.Request) | |
| return result | |
| # Get all models and filter | |
| models = self.info() | |
| assert isinstance(models, List) | |
| # Find the matching model | |
| for model in models: | |
| if (model_id and model.get("model_info", {}).get("id") == model_id) or ( | |
| model_name and model.get("model_name") == model_name | |
| ): | |
| return model | |
| # If we get here, no model was found | |
| if model_id: | |
| msg = f"Model with id={model_id} not found" | |
| elif model_name: | |
| msg = f"Model with model_name={model_name} not found" | |
| else: | |
| msg = "Unknown error trying to find model" | |
| raise NotFoundError( | |
| requests.exceptions.HTTPError( | |
| msg, | |
| response=requests.Response(), # Empty response since we didn't make a direct request | |
| ) | |
| ) | |
| def info(self, return_request: bool = False) -> Union[List[Dict[str, Any]], requests.Request]: | |
| """ | |
| Get detailed information about all models from the server. | |
| Args: | |
| return_request (bool): If True, returns the prepared request object instead of executing it | |
| Returns: | |
| Union[List[Dict[str, Any]], requests.Request]: Either a list of model information dictionaries | |
| or a prepared request object if return_request is True | |
| Raises: | |
| UnauthorizedError: If the request fails with a 401 status code | |
| requests.exceptions.RequestException: If the request fails with any other error | |
| """ | |
| url = f"{self._base_url}/v1/model/info" | |
| request = requests.Request("GET", url, headers=self._get_headers()) | |
| if return_request: | |
| return request | |
| # Prepare and send the request | |
| session = requests.Session() | |
| try: | |
| response = session.send(request.prepare()) | |
| response.raise_for_status() | |
| return response.json()["data"] | |
| except requests.exceptions.HTTPError as e: | |
| if e.response.status_code == 401: | |
| raise UnauthorizedError(e) | |
| raise | |
| def update( | |
| self, | |
| model_id: str, | |
| model_params: Dict[str, Any], | |
| model_info: Optional[Dict[str, Any]] = None, | |
| return_request: bool = False, | |
| ) -> Union[Dict[str, Any], requests.Request]: | |
| """ | |
| Update an existing model's configuration. | |
| Args: | |
| model_id (str): ID of the model to update | |
| model_params (Dict[str, Any]): New parameters for the model (e.g., model type, api_base, api_key) | |
| model_info (Optional[Dict[str, Any]]): Additional information about the model | |
| return_request (bool): If True, returns the prepared request object instead of executing it | |
| Returns: | |
| Union[Dict[str, Any], requests.Request]: Either the response from the server or | |
| a prepared request object if return_request is True | |
| Raises: | |
| UnauthorizedError: If the request fails with a 401 status code | |
| NotFoundError: If the model is not found | |
| requests.exceptions.RequestException: If the request fails with any other error | |
| """ | |
| url = f"{self._base_url}/model/update" | |
| data = { | |
| "id": model_id, | |
| "litellm_params": model_params, | |
| } | |
| if model_info: | |
| data["model_info"] = model_info | |
| request = requests.Request("POST", url, headers=self._get_headers(), json=data) | |
| if return_request: | |
| return request | |
| # Prepare and send the request | |
| session = requests.Session() | |
| try: | |
| response = session.send(request.prepare()) | |
| response.raise_for_status() | |
| return response.json() | |
| except requests.exceptions.HTTPError as e: | |
| if e.response.status_code == 401: | |
| raise UnauthorizedError(e) | |
| if e.response.status_code == 404 or "not found" in e.response.text.lower(): | |
| raise NotFoundError(e) | |
| raise | |