From 951102292be0149505ff5b1e08c5e109f4735516 Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Fri, 23 Feb 2024 15:17:22 -0800 Subject: [PATCH 1/4] fix(utils.py): add more logging statements --- litellm/utils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/litellm/utils.py b/litellm/utils.py index 4468d7c501..c67baef3c5 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -4300,6 +4300,7 @@ def get_optional_params( or model in litellm.vertex_language_models or model in litellm.vertex_embedding_models ): + print_verbose(f"(start) INSIDE THE VERTEX AI OPTIONAL PARAM BLOCK") ## check if unsupported param passed in supported_params = [ "temperature", @@ -4333,6 +4334,9 @@ def get_optional_params( optional_params["tools"] = [ generative_models.Tool(function_declarations=gtool_func_declarations) ] + print_verbose( + f"(end) INSIDE THE VERTEX AI OPTIONAL PARAM BLOCK - optional_params: {optional_params}" + ) elif custom_llm_provider == "sagemaker": ## check if unsupported param passed in supported_params = ["stream", "temperature", "max_tokens", "top_p", "stop", "n"] @@ -4748,6 +4752,7 @@ def get_optional_params( extra_body # openai client supports `extra_body` param ) else: # assume passing in params for openai/azure openai + print_verbose(f"UNMAPPED PROVIDER, ASSUMING IT'S OPENAI/AZUREs") supported_params = [ "functions", "function_call", @@ -4823,6 +4828,7 @@ def get_optional_params( for k in passed_params.keys(): if k not in default_params.keys(): optional_params[k] = passed_params[k] + print_verbose(f"Final returned optional params: {optional_params}") return optional_params From 485f5bd14042b9c098414da2a619a3b2528e3fc4 Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Fri, 23 Feb 2024 15:17:39 -0800 Subject: [PATCH 2/4] =?UTF-8?q?bump:=20version=201.26.13=20=E2=86=92=201.2?= =?UTF-8?q?6.14.dev1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b4bc7d69d0..3328081779 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "litellm" -version = "1.26.13" +version = "1.26.14.dev1" description = "Library to easily interface with LLM API providers" authors = ["BerriAI"] license = "MIT" @@ -74,7 +74,7 @@ requires = ["poetry-core", "wheel"] build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "1.26.13" +version = "1.26.14.dev1" version_files = [ "pyproject.toml:^version" ] From f3be073f7257676ac6f875acfe04fe447661de13 Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Fri, 23 Feb 2024 19:56:00 -0800 Subject: [PATCH 3/4] fix(proxy_server.py): enable end-users to opt out of llm api calls --- litellm/proxy/_types.py | 4 ++ litellm/proxy/proxy_server.py | 87 +++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index 7f453980fb..029f35867e 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -116,6 +116,10 @@ class ModelInfo(LiteLLMBase): return values +class BlockUsers(LiteLLMBase): + user_ids: List[str] # required + + class ModelParams(LiteLLMBase): model_name: str litellm_params: dict diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 1a8e4dddc6..a9fb6d700a 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -4302,6 +4302,93 @@ async def user_get_requests(): ) +@router.post( + "/user/block", + tags=["user management"], + dependencies=[Depends(user_api_key_auth)], +) +async def block_user(data: BlockUsers): + """ + [BETA] Reject calls with this user id + + ``` + curl -X POST "http://0.0.0.0:8000/user/block" + -H "Authorization: Bearer sk-1234" + -D '{ + "user_ids": [, ...] + }' + ``` + """ + from litellm.proxy.enterprise.enterprise_hooks.blocked_user_list import ( + _ENTERPRISE_BlockedUserList, + ) + + if not any(isinstance(x, _ENTERPRISE_BlockedUserList) for x in litellm.callbacks): + blocked_user_list = _ENTERPRISE_BlockedUserList() + litellm.callbacks.append(blocked_user_list) # type: ignore + + if litellm.blocked_user_list is None: + litellm.blocked_user_list = data.user_ids + elif isinstance(litellm.blocked_user_list, list): + litellm.blocked_user_list = litellm.blocked_user_list + data.user_ids + else: + raise HTTPException( + status_code=500, + detail={ + "error": "`blocked_user_list` must be a list or not set. Filepaths can't be updated." + }, + ) + + return {"blocked_users": litellm.blocked_user_list} + + +@router.post( + "/user/unblock", + tags=["user management"], + dependencies=[Depends(user_api_key_auth)], +) +async def unblock_user(data: BlockUsers): + """ + [BETA] Unblock calls with this user id + + Example + ``` + curl -X POST "http://0.0.0.0:8000/user/unblock" + -H "Authorization: Bearer sk-1234" + -D '{ + "user_ids": [, ...] + }' + ``` + """ + from litellm.proxy.enterprise.enterprise_hooks.blocked_user_list import ( + _ENTERPRISE_BlockedUserList, + ) + + if ( + not any(isinstance(x, _ENTERPRISE_BlockedUserList) for x in litellm.callbacks) + or litellm.blocked_user_list is None + ): + raise HTTPException( + status_code=400, + detail={ + "error": "Blocked user check was never set. This call has no effect." + }, + ) + + if isinstance(litellm.blocked_user_list, list): + for id in data.user_ids: + litellm.blocked_user_list.remove(id) + else: + raise HTTPException( + status_code=500, + detail={ + "error": "`blocked_user_list` must be set as a list. Filepaths can't be updated." + }, + ) + + return {"blocked_users": litellm.blocked_user_list} + + #### TEAM MANAGEMENT #### From edaf20b60a649b12a91da63cb9785cdc88392826 Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Sat, 24 Feb 2024 09:28:41 -0800 Subject: [PATCH 4/4] docs(enterprise.md): add end user opt out to docs --- docs/my-website/docs/proxy/enterprise.md | 25 +++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/my-website/docs/proxy/enterprise.md b/docs/my-website/docs/proxy/enterprise.md index 3e97780213..a4f3ea7b17 100644 --- a/docs/my-website/docs/proxy/enterprise.md +++ b/docs/my-website/docs/proxy/enterprise.md @@ -1,7 +1,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# ✨ Enterprise Features - Content Moderation, Blocked Users/Keywords +# ✨ Enterprise Features - End-user Opt-out, Content Mod Features here are behind a commercial license in our `/enterprise` folder. [**See Code**](https://github.com/BerriAI/litellm/tree/main/enterprise) @@ -167,6 +167,29 @@ curl --location 'http://0.0.0.0:8000/chat/completions' \ ::: +### Using via API + + +**Block all calls for a user id** + +``` +curl -X POST "http://0.0.0.0:8000/user/block" \ +-H "Authorization: Bearer sk-1234" \ +-D '{ +"user_ids": [, ...] +}' +``` + +**Unblock calls for a user id** + +``` +curl -X POST "http://0.0.0.0:8000/user/unblock" \ +-H "Authorization: Bearer sk-1234" \ +-D '{ +"user_ids": [, ...] +}' +``` + ## Enable Banned Keywords List ```yaml