From f7e92bb0db368afda96f27f29fa6e073788ccc71 Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Thu, 14 Sep 2023 16:22:49 -0700 Subject: [PATCH] make max budget work for openai streaming --- litellm/__init__.py | 1 + litellm/__pycache__/__init__.cpython-311.pyc | Bin 8271 -> 8442 bytes litellm/__pycache__/main.cpython-311.pyc | Bin 32578 -> 32938 bytes litellm/__pycache__/utils.cpython-311.pyc | Bin 106427 -> 107596 bytes litellm/tests/test_litellm_max_budget.py | 30 ++++++++++++------- litellm/utils.py | 23 ++++++++++---- 6 files changed, 38 insertions(+), 16 deletions(-) diff --git a/litellm/__init__.py b/litellm/__init__.py index 03114b78e..b0099202e 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -269,6 +269,7 @@ from .exceptions import ( ServiceUnavailableError, OpenAIError, ContextWindowExceededError, + BudgetExceededError ) from .budget_manager import BudgetManager diff --git a/litellm/__pycache__/__init__.cpython-311.pyc b/litellm/__pycache__/__init__.cpython-311.pyc index 9d7f4f02b45a07e21ea401f93f7eb5ebbe5828c5..8b54c3254f72a34473ddb63d92a0b3a61fb3a172 100644 GIT binary patch delta 666 zcmX@_@XJwsIWI340}upGWlr^%XJB{?;=lk8l=1n+M)mE?94W>rCh1I39+U4e2XcC* zGo+XdY{8!BE>StH`h1HmyrR;w#xAf0nyeulN(ta zeR30`5}@LVU~#LQBrt80lbo9pm6Dqpm71Ftm6n?xm7bdsm64knm6@9rl?B#go0FZJ z6O{vGGX^tg+HGcIKb%1qTYFfgnV0P~X)ladnCAtF3rk;Ifltnx-s z9h+Tv#Mq6i#1eB8tMc>oN-|3l^K?tn4Rv!8i_%l8#1k`(4E3^%bkmCx^HNfEGxLf| zib|79GzBNe2v6cK@&^XjEw<#+;*$JaP43A*gpHVr{5PwML@_e5Pi_*e;kYI2RGN~W zS~B^gs61otWOdNbksVPPI$=Q=%OMDbB$^{w0mjqT7pPQHmbbnD%-sE?ZvcmI$ zQj9=c9LUDN@PV0;k@3c4MJe&krcwgTLhMRR9~fZ71qQhfLX$&e_wvf#V3Ga6$}Ggx z!1sY?GQV7hppYO?A&h9?{h&2@g`Aeq4Sv}V;yhwNDIjryLFj|r=7(~OjOCn+Kp|QX RA`FaL7Z@}#QIQGIivT-ByLtcs delta 478 zcmez6c-}#MIWI340}vc2VNR`;V_8w$hOGw4FS=XIexkRQIp$Q99^K|31D%H zoJ25fm6Md49F?4#5|xsh8kL%x7L}Hp9+jS(5tRW}Z=I8wn-!G>WHSacXxeNRVdZDn z=S(gw%1qTYFfgp*PD)HlN=%1v*b`F{(M64_xHo6>h_N$i3QXQ2Jc;WTTXJb}Nq(*- z*W^$Uqs=`c;f#!Ilb?vzOfD4@V$9y$A@+!Aa+Tyup<8@Or77vDCGok5c|Z$_igG7c zNy&1}1qKQu5EmP5UMOY2%+H`y&3Hkv3WONsKCn!FEW3B|dbu`1K|!Vu3^1aB_k+e{ mH+e1o52D;+Kye^(fkEhl%;qL}M#caRMxYS&2%*V$6=VUlFobXb diff --git a/litellm/__pycache__/main.cpython-311.pyc b/litellm/__pycache__/main.cpython-311.pyc index 3b91b0fb33e88bd4119a01f41f07a841536dc4e7..fcec8b4e6d946fabb1d78e90a2401d98d2c1a08a 100644 GIT binary patch delta 1429 zcmY*XZA@EL7(Va4r7fkG_Hs*a3oT_ZXc=^+fWzUot{~rvA}+H=zCzIeQVOlO&D(V| zGrC9?$eGzREE`5$6fjwiA6a5zx`Y^`AX{dlMop$JCQA%=kv|fq-gD`Ko*(CVp7Xrt zea<=eUi%w9ILTyR<~RdV#^w=ruy6iKcF4qhQi6v}Ls`ioB$d1aXP^sV-fSg*ntB0} zq>CS8Ac;GR^6*c>JZp}Wkk>6q#i2{2#99mR8R-^vOh!^dk{6E)A~|7S1-M2!^BaIQ zMqK2a!wc{lS#stBY>-<80bmW05GgM7Znb_x>Gpe3FML6oi_3u3NBktV^CGaiNFT{9 zEd%(91l-LGTqduU*%^3?%$56r)kF~fwqnV2L9&O3Mi_dliSGFOI9RY3JG?zGgi{4h zo{iKg{&3oVJU*ZH^YEs37Yx%H9TWLYsTslTyAQ+jnD-pihDW7?LxBBufm@`Fx5n^c zoax)^ioB{Bp)1@~8q5W?4O zRvfH!!F@fKn~Tp>R)`a`tWsM?YbAH0d>SHi%E4mzdZo)1Pp4cA#}amlkM45P>kIZI-kIpg+$Nv91 ziB_rgQa_&Y6zkeDk<=D`3D4w-AStsIC#y%f|MpJczp8!0(sr8iOWCE0h2!|4njLV0 zbl05IgNWsQuRsx*+}{DpIhGDA!T^Z{rdf@sY$Qy>3d5YX;Tw%r%p*pkZ5k1{)*GC6 zmGjP6mRZn%%}K6PQ8`lk7e~7#h+{I3n|{R zwYVwXK@Db#fAIAdipjN7HGHj3GZsK=2h_B+03S88viV^nEm?PJ;zekEhia`C@$qVQ zy}EHfwKn|0B8r=qExcD7%%%DtuHHm36?8UwRMM<%s8mT?ts&TMV^i&r6Koe)U8-Hk zP!{mwgh+nrc^TksGT4{Wz^}wTC<4eN@a&ra3*`Ifp3uWOsfb2dc#vF(DPBGKIQ}6( z6A4d#l%afDyVRDHj9`$__WWH|w#=$hi%f#7Q>h-AEpnzx4ag$OSt>Q698u;}nvIOS zY*MKi>9b^Br8$V>WkID@#9L)ir8XowWV=coD9Pu_PL&rRCE2A?53)GUH=Nxsm#K0W z%C=4qOm)lUs;odcdFPAII%TgacO#QH9h(}JeX48$lqF18PkH55P#4+&38LJ-C7uMN l734!(g5J6?efhgOhGEu`GTmhnqd#Sp_3G~9q+S}XqQfND%K-)n_UqG@&D5dM5sL0%W!HA$MYC+0dx4C(t zk}UDVh_W0OX0l~$QHe4&=4gzG%j}kYFafs2mpJ20mY5h#43|hu+?;yPfrL-q59jy) zpXWT!bDop?{xo;>A1Gcl7z&a4-Rk5At}T9C++*aFDx5N=^iwG$SHBH!zyX8>la2gg z>;sr02ZRw0rttpCQhZxn;*II68BCpwR0`!sn zWijCO=`YBW95Gut3VJ93>-=dmtU+Ba1Vqb<$&ZB2F$yd&D zmyW%wKIjsARN8McAtx64@hPtxn;Num9G@zc;8k_C;dsNa;qvyKk}|&1P%mEF-cf%G zyIgl^5<_DJWQn_RUWczVPlKLBTe<-H@oeM+c%HPh&hq5z*b2wpmGH%VA?~oAe7A2% zBsZUaHZS{^TJIe(ny{eHJNy)1d14afa>VcWKl<7Xls`4Kl~dj+>F`kghGHhl--R{{Wp=HGHDBA4HxfZ> zEv(yGL>M*kifL~VJ+k4<%T%I`3KrU^6f$9cBOGt0p}WCoCFS3isFm{m&Nd_EzkA|d z%3RzX3owze6h;$`d@kWKM-u^+0S)zsNMrvzz)7<5TrLlm$(t`o0Jq5Ei*Es(CehSm zI=D^d#zuLlAezH!td=;Bdm)c z?Lunj9ZY(W#c?J!*R1%M-HD2AvxjDSm0D)&kh%1Xd(Nr&ncanq((J^{uu{)#2OzyT z8=mni31AzYfJ8}oXww`7q!pFNHw~S-d~5jie2(Kbkh-k%h|`_0DLR(jO@5uq!GF9t BWp4lg diff --git a/litellm/__pycache__/utils.cpython-311.pyc b/litellm/__pycache__/utils.cpython-311.pyc index d323a9eaefad64aba61db22e26fc245aea144e49..11ad024d4bcee8d931fe04c8b3a6a699ec7ecf78 100644 GIT binary patch delta 12153 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 aZj6$;5Asr0=^>?87lAvB-3#`CZ2Uj1TVYoK delta 11234 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 GG5;?OO^j{; diff --git a/litellm/tests/test_litellm_max_budget.py b/litellm/tests/test_litellm_max_budget.py index 15ca48efe..0e933c604 100644 --- a/litellm/tests/test_litellm_max_budget.py +++ b/litellm/tests/test_litellm_max_budget.py @@ -1,6 +1,6 @@ -#### What this tests #### -# This tests calling litellm.max_budget by making back-to-back gpt-4 calls -# commenting out this test for circle ci, as it causes other tests to fail, since litellm.max_budget would impact other litellm imports +# #### What this tests #### +# # This tests calling litellm.max_budget by making back-to-back gpt-4 calls +# # commenting out this test for circle ci, as it causes other tests to fail, since litellm.max_budget would impact other litellm imports # import sys, os, json # import traceback # import pytest @@ -9,13 +9,23 @@ # 0, os.path.abspath("../..") # ) # Adds the parent directory to the system path # import litellm -# litellm.set_verbose = True -# from litellm import completion +# # litellm.set_verbose = True +# from litellm import completion, BudgetExceededError -# litellm.max_budget = 0.001 # sets a max budget of $0.001 +# def test_max_budget(): +# try: +# litellm.max_budget = 0.001 # sets a max budget of $0.001 + +# messages = [{"role": "user", "content": "Hey, how's it going"}] +# response = completion(model="gpt-4", messages=messages, stream=True) +# for chunk in response: +# continue +# print(litellm._current_cost) +# completion(model="gpt-4", messages=messages, stream=True) +# litellm.max_budget = float('inf') +# except BudgetExceededError as e: +# pass +# except Exception as e: +# pytest.fail(f"An error occured: {str(e)}") -# messages = [{"role": "user", "content": "Hey, how's it going"}] -# completion(model="gpt-4", messages=messages) -# completion(model="gpt-4", messages=messages) -# print(litellm._current_cost) diff --git a/litellm/utils.py b/litellm/utils.py index 69f53a877..7df4330c4 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -180,6 +180,10 @@ class Logging: # Log the exact input to the LLM API print_verbose(f"Logging Details Pre-API Call for call id {self.litellm_call_id}") try: + if start_time is None: + start_time = self.start_time + if end_time is None: + end_time = datetime.datetime.now() # print_verbose(f"logging pre call for model: {self.model} with call type: {self.call_type}") self.model_call_details["input"] = input self.model_call_details["api_key"] = api_key @@ -202,6 +206,11 @@ class Logging: f"LiteLLM.LoggingError: [Non-Blocking] Exception occurred while logging {traceback.format_exc()}" ) + if litellm.max_budget and self.stream: + time_diff = (end_time - start_time).total_seconds() + float_diff = float(time_diff) + litellm._current_cost += litellm.completion_cost(model=self.model, prompt="".join(message["content"] for message in self.messages), completion="", total_time=float_diff) + # Input Integration Logging -> If you want to log the fact that an attempt to call the model was made for callback in litellm.input_callback: try: @@ -314,6 +323,12 @@ class Logging: if end_time is None: end_time = datetime.datetime.now() print_verbose(f"success callbacks: {litellm.success_callback}") + + if litellm.max_budget and self.stream: + time_diff = (end_time - start_time).total_seconds() + float_diff = float(time_diff) + litellm._current_cost += litellm.completion_cost(model=self.model, prompt="", completion=result["content"], total_time=float_diff) + for callback in litellm.success_callback: try: if callback == "lite_debugger": @@ -574,10 +589,6 @@ def client(original_function): if litellm.caching or litellm.caching_with_models or litellm.cache != None: # user init a cache object litellm.cache.add_cache(result, *args, **kwargs) - # [OPTIONAL] UPDATE BUDGET - if litellm.max_budget: - litellm._current_cost += litellm.completion_cost(completion_response=result) - # [OPTIONAL] Return LiteLLM call_id if litellm.use_client == True: result['litellm_call_id'] = litellm_call_id @@ -2383,7 +2394,6 @@ class CustomStreamWrapper: def handle_cohere_chunk(self, chunk): chunk = chunk.decode("utf-8") - print(f"cohere chunk: {chunk}") data_json = json.loads(chunk) try: print(f"data json: {data_json}") @@ -2474,7 +2484,8 @@ class CustomStreamWrapper: completion_obj["content"] = self.handle_cohere_chunk(chunk) else: # openai chat/azure models chunk = next(self.completion_stream) - return chunk # open ai returns finish_reason, we should just return the openai chunk + completion_obj["content"] = chunk["choices"][0]["delta"]["content"] + # return chunk # open ai returns finish_reason, we should just return the openai chunk #completion_obj["content"] = self.handle_openai_chat_completion_chunk(chunk) # LOGGING