From a4cf7e1edde0ed95b52d58e1e1a7109eb0a0cefe Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Sat, 12 Aug 2023 17:39:11 -0700 Subject: [PATCH] added exception mapping to anthropic class --- litellm/__pycache__/main.cpython-311.pyc | Bin 21031 -> 20953 bytes litellm/__pycache__/utils.cpython-311.pyc | Bin 39112 -> 39117 bytes litellm/llms/anthropic.py | 24 ++++++++++++---------- litellm/llms/base.py | 11 ++++++++++ litellm/main.py | 2 +- litellm/tests/test_exceptions.py | 9 ++++---- 6 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 litellm/llms/base.py diff --git a/litellm/__pycache__/main.cpython-311.pyc b/litellm/__pycache__/main.cpython-311.pyc index c0ed4c412b3ab41afdd4de74d27497ccf3fdaf60..33583922613e2e8907306a394bc8b762fe5fa833 100644 GIT binary patch delta 1289 zcmZ8eZA@EL7{2elYw6n2LTQ<|w57-#!%|B5+DgYqfsGa!WwP-H9FksIrfU~&U@m&^ z7X0|B+wy93VIRdI{GiU66Tf0&viZXpO~%Yv1Yjv6Xp0A~y( zkR@*!R$yDfYeoxXS%F$Fr+t#$^5ziPvYg`GB}GL z75ng^(}ZR2Lj0rHtP?nHNkFi^4fEu(^~Y@&6iMbQ!j_^goxwR{)rRT_SQ3zr}dR?(e2cGBI>n?&Ely*zpsXDbr3M$+zca>LtQza~y8&b;x(EI7k z4YgJZNe7i$R(TRsKl&{qv|?dt?=GoLaZ;*IsmTQJ-Yz@3MLo3R6QYM#Y~7 zIwT!teR>ZRf3^odDf1L5Hf5*M@SH#YEDV>6XmmQn@B(ejlGYrSQyq$9kW(7AOj{sA z#+;)74S3rnLKOXG`|d`yk(%y3)s$*hn^ODLX5f^@%mMA4^cNwBlX|YUEp z0B&j~zvejFhF~^^GoA`KN^W?55=_FHVLTl_EuBm!$*X%l20Xs^7t&w#3J+oOU3CrU zc_xImuuG|EU>+t9ZiK;Yu@Nj=~xrKP}I*ML~EV zI(q!+K3T@keeXh&oT&8|xZXdzGW5*-p^0Vr{GS}>2=f~nZfZ!bHT})wT;sR6*ITJg8wzK-SAf#u1U=!rpon5V^q{IfjW#bIn)NbzUbuHXeGN|Dx4)EE+Jv4EAS zjEpbq6ZiCq`}zc3U@~-QyZBH}d^o2%vMo&TlbV#QiOZU}oMXrjp;f+as)}3DcQ@0p z+8VLZ@UykoLBm5|PmqSqD&w?U*bMBO7KOh=-L#wh+SVt)9Sn4K!(DQwGpsAA-XXWK zMs_i1XW+xndcLHephkT9n~eAXZ$iAy%`d-YAadGhW#r{|sX zJLh-LOE*7&tCu13s!F9mRLN%c9Au zh=r}=&=NY&M64mrj;i_?&=T@3B;s0bHh0OVZtvlQ{?h6=qqCVT}Vr$|1R-;cQJBw3~JKeE_ds3%@y z0~l(=W=3v#U-#-1WG^plCAyAohXU+JfyDVGMDXj;(Ct7cxcoh|!S zb8XktVJrEi>~#j*WUAZ(immjqz~~fvJTQTy`m}$U z_pP?HtgjsF?t%F5WL)o0=>6+@Ke5$3WSpzv_`vWV2%QEWLrpt$?l8|YNBLiABg_Lq z|0!r8f`{#kId|l`ceQJBQ=C3#`)8^(vnOHp;K$Avcdv$T%HuL$LgrhS`KW^fuD$g_ zv-r#`#W@Xa$wrNlDFVJW&TYvawP!>gs{rwm^cHNPp_UDRw#72yWSwt8>aA=!3F z!wqDisY^ot&(>PoAVG2uv`U#^2%l{Kf-cYIwaTvZd$@s*c}tZa^KKEZZsJ9+88!&< z7E5Gfd}NG#-+2+>I)1g=0rxQJUQ+(R$Bn#N#z%UV;C;N^vuAgL4{Qh}yt;=iy(ajb J_Lqq diff --git a/litellm/__pycache__/utils.cpython-311.pyc b/litellm/__pycache__/utils.cpython-311.pyc index fece25c518bdf695bf8c4d26cc50322512c7cb41..200ddc9d0bca20a5781e6eade5d4703da7efba67 100644 GIT binary patch delta 422 zcmX@Hk?HJ4Ccfpoyj%=G@J!`K%D>i)e2gNTE14J=8W=t>sZN#<31hy&&a=5#M462- zZ}W61X(k~(pyHLxMLIyLNFPM#O+F&y&Zsw;N7jX{0Vq&BcXF7lpM_)Cg{XuJjv%yv z?Si_^6$RT1K$MnsflKx-m)wHT4Vf20GcIstUgXNW!j%bRK+xu^vdzql-J2s7*D^BZ zZe~}OWMW*rSy8o`nQ_DBxf%vcj3+jq(`sO3JipmrN1v7P<>q=rV^&7L&6~~a7#ZC+ ze=?8eVvO4C=aeYS*t>Z{=pzBfpPMJAt!HC2o9vu>n9*c2dtN&uqtoX8`~Y@FkIfIt z3R!GGp1Q@7l30>h%mQR806~!$kWmy5Biew0QtSofH84Ej7r84eHlcE&-4weUvId)b zs|8pX`!>(3zs=0JWphxmhxB5I7B9~e-Hkj>kt2{HiysR4=Q delta 390 zcmX@Rk?F)nCcfpoyj%=GFkS3MN^aXmK1LDF)l3Ww4GbTcG$%`lgt30$V&LH2TqvT< z##pp@s+2U7kSVQs!Z>O3;`-anj5{{hH}fzt zo|@d#dYjEvVevvw#kG2Yv((G|qZ_;Pb~Zw4dd$<0stqL`Q%m^V92%wQGK RV&we5fJ(${-ZM>*2>|YYf7}27 diff --git a/litellm/llms/anthropic.py b/litellm/llms/anthropic.py index 5e755e34c3..5b5d928b20 100644 --- a/litellm/llms/anthropic.py +++ b/litellm/llms/anthropic.py @@ -4,13 +4,20 @@ import requests from litellm import logging import time from typing import Callable + class AnthropicConstants(Enum): HUMAN_PROMPT = "\n\nHuman:" AI_PROMPT = "\n\nAssistant:" +class AnthropicError(Exception): + def __init__(self, status_code, message): + self.status_code = status_code + self.message = message + class AnthropicLLM: - def __init__(self, default_max_tokens_to_sample, api_key=None): + def __init__(self, encoding, default_max_tokens_to_sample, api_key=None): + self.encoding = encoding self.default_max_tokens_to_sample = default_max_tokens_to_sample self.completion_url = "https://api.anthropic.com/v1/complete" self.validate_environment(api_key=api_key) @@ -33,9 +40,6 @@ class AnthropicLLM: raise ValueError("Missing Anthropic API Key - A call is being made to anthropic but no key is set either in the environment variables or via params") pass - def _stream(self): # logic for handling streaming with the LLM API - pass - def completion(self, model: str, messages: list, model_response: dict, print_verbose: Callable, optional_params=None, litellm_params=None, logger_fn=None): # logic for parsing in - calling - parsing out model completion calls model = model prompt = f"{AnthropicConstants.HUMAN_PROMPT.value}" @@ -73,12 +77,13 @@ class AnthropicLLM: completion_response = response.json() print(f"completion_response: {completion_response}") if "error" in completion_response: - raise Exception(completion_response["error"]) + raise AnthropicError(message=completion_response["error"], status_code=response.status_code) else: model_response["choices"][0]["message"]["content"] = completion_response["completion"] + ## CALCULATING USAGE - prompt_tokens = 0 - completion_tokens = 0 + prompt_tokens = len(self.encoding.encode(prompt)) ##[TODO] use the anthropic tokenizer here + completion_tokens = len(self.encoding.encode(model_response["choices"][0]["message"]["content"])) ##[TODO] use the anthropic tokenizer here model_response["created"] = time.time() @@ -91,7 +96,4 @@ class AnthropicLLM: return model_response def embedding(): # logic for parsing in - calling - parsing out model embedding calls - pass - - def stream(): # logic for how to parse in-out model completion streams - pass \ No newline at end of file + pass \ No newline at end of file diff --git a/litellm/llms/base.py b/litellm/llms/base.py new file mode 100644 index 0000000000..368df96245 --- /dev/null +++ b/litellm/llms/base.py @@ -0,0 +1,11 @@ +## This is a template base class to be used for adding new LLM providers via API calls + +class BaseLLM(): + def validate_environment(): # set up the environment required to run the model + pass + + def completion(): # logic for parsing in - calling - parsing out model completion calls + pass + + def embedding(): # logic for parsing in - calling - parsing out model embedding calls + pass \ No newline at end of file diff --git a/litellm/main.py b/litellm/main.py index bead3e1d86..9ee8beaefb 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -208,7 +208,7 @@ def completion( response = model_response elif model in litellm.anthropic_models: anthropic_key = api_key if api_key is not None else litellm.anthropic_key - anthropic_client = AnthropicLLM(default_max_tokens_to_sample=litellm.max_tokens, api_key=anthropic_key) + anthropic_client = AnthropicLLM(encoding=encoding, default_max_tokens_to_sample=litellm.max_tokens, api_key=anthropic_key) model_response = anthropic_client.completion(model=model, messages=messages, model_response=model_response, print_verbose=print_verbose, optional_params=optional_params, litellm_params=litellm_params, logger_fn=logger_fn) if 'stream' in optional_params and optional_params['stream'] == True: # don't try to access stream object, diff --git a/litellm/tests/test_exceptions.py b/litellm/tests/test_exceptions.py index 16f7ae65d4..e224fdf7a6 100644 --- a/litellm/tests/test_exceptions.py +++ b/litellm/tests/test_exceptions.py @@ -21,7 +21,8 @@ litellm.failure_callback = ["sentry"] # Approach: Run each model through the test -> assert if the correct error (always the same one) is triggered # models = ["gpt-3.5-turbo", "chatgpt-test", "claude-instant-1", "command-nightly"] -models = ["command-nightly"] +test_model = "claude-instant-1" +models = ["claude-instant-1"] def logging_fn(model_call_dict): if "model" in model_call_dict: print(f"model_call_dict: {model_call_dict['model']}") @@ -35,7 +36,7 @@ def test_context_window(model): sample_text = "how does a court case get to the Supreme Court?" * 5000 messages = [{"content": sample_text, "role": "user"}] try: - azure = model == "chatgpt-test" + model = "chatgpt-test" print(f"model: {model}") response = completion(model=model, messages=messages, custom_llm_provider="azure", logger_fn=logging_fn) print(f"response: {response}") @@ -51,7 +52,7 @@ def test_context_window(model): print(f"Uncaught Exception - {e}") pytest.fail(f"Error occurred: {e}") return -test_context_window("command-nightly") +test_context_window(test_model) # Test 2: InvalidAuth Errors @pytest.mark.parametrize("model", models) @@ -101,7 +102,7 @@ def invalid_auth(model): # set the model key to an invalid key, depending on the elif model == "replicate/llama-2-70b-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1": os.environ["REPLICATE_API_KEY"] = temporary_key return -invalid_auth("command-nightly") +invalid_auth(test_model) # # Test 3: Rate Limit Errors # def test_model(model): # try: