From 253e8d27db326d25d068488019298bbfa7a5098a Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Mon, 9 Oct 2023 16:46:18 -0700 Subject: [PATCH] fix: bug fix when n>1 passed in --- docs/my-website/docs/completion/input.md | 4 +- litellm/__pycache__/utils.cpython-311.pyc | Bin 159033 -> 159723 bytes litellm/llms/ai21.py | 14 ++-- litellm/llms/cohere.py | 17 +++-- litellm/llms/palm.py | 43 ++++++----- litellm/llms/together_ai.py | 2 +- .../tests/test_provider_specific_config.py | 67 ++++++++++++++++-- litellm/utils.py | 15 +++- 8 files changed, 119 insertions(+), 43 deletions(-) diff --git a/docs/my-website/docs/completion/input.md b/docs/my-website/docs/completion/input.md index 0eebb13a7..892cc17c6 100644 --- a/docs/my-website/docs/completion/input.md +++ b/docs/my-website/docs/completion/input.md @@ -32,7 +32,7 @@ This list is constantly being updated. |---|---|---|---|---|---|---|---|---|---|---| |Anthropic| ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | |OpenAI| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -|Replicate | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | +|Replicate | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | |Cohere| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | |Huggingface| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | |Openrouter| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | @@ -43,7 +43,7 @@ This list is constantly being updated. |TogetherAI| ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | |AlephAlpha| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | |Palm| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | -|NLP Cloud| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | +|NLP Cloud| ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | |Petals| ✅ | ✅ | | ✅ | | | | | | | |Ollama| ✅ | ✅ | ✅ | ✅ | ✅ | | | ✅ | | |n diff --git a/litellm/__pycache__/utils.cpython-311.pyc b/litellm/__pycache__/utils.cpython-311.pyc index 1f1eab4bb5a1ddf2c35b1c2239cf350555e2402c..d3da8727b3b5f036009efe20cf35b019185fd94a 100644 GIT binary patch delta 22224 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 delta 21453 zcmbt+33yaR)^^uTcW3GBAwV_=5S9iK_AP9QVPC=$Kp<+T$?ZTx(jBWiAQ9*&sNlwO zNA5U+Be;QpiV^!$#{p;DzHtM^QSYdz!_0i@s5p$X=rI20J-3%6^3VT0&mSI6>eh1V zoKvSxojO&OFU}=DZ6v2ZoR*eip`T)Ji6`l+-RV8W(c=SOR?5`8ZI+d*)O=5EgQ6B} zv#zXHEHf=?;Wmp}TOWBsFOXl>J%cQ zmdOY)Ee%$6Dv@!WT0w=CvBGHC6*L|j(U8WbiqfrdV$@IsVXZoi+7eoIhUa>9rsw*G zRCN~N+{9f*yJL*%Y|m!uaSoMk2~qJ}qAaA&BT==f^9kOdRujBYT|jWFx{%;D?qm@W zU{x0r0XL~NlzX$<#`#M;o7JV%@iHn;Qm-Vmw-DCl+k|_&x`OKM@LC##x{`XiRlPy2 zrQf%yS5f}$>ebsqmX&v?*U-nEJhCnt*}BdnyK<-Mrt)1(wW6+~?su#8o@t)VkVnU{ zR8=b5qk5>e=C#m}Oi(8f!41^mPt?_vdzZR~;9k{BP*>Ly{HZq5o;@ilPW49Or?aU1 zo_%VwXMclTy_Wd8SC!Q0=bj!+Y=DRjYPZ{q#C=+u-6;-eN9{e6RvuJEjm5dO{jc_^ zigwJg(RLA1*OsJ|cQaC5t35uCbO${yuPVzZU)83imWZL6H}!!*!{|F82o%dwf<{)8 zyV=#?^?3tpT+-tX_ZO0zO*k3htRjvZrB1X%^oSoqE(X1MNNV(m)4wK zu+XpuJdF)%N-t3m{rht*`a@9Aw0|A#SV5j_I{IqfBauR*FX3qBn0`AqG zvMA1G?QHt2tf5rqOpxQ~mmE)^TKgeo;Bd4s(jpk^J&lbn*I^;Apj>9E!o&+2nNYtr zKVya+sN`7UWw7?^j6v!;m9NVF6tQ7r!?liq6JVR|u2 z5~FF@ygt=)ojEXxO{OrTOrU~X1h5$3|G`9N)f&II-V-RJF*C=vO{>cZMfs30h5r{` zn6PTCIxA1>(`|$)^6K{G-G+!-mUp5_|58xF^v5Y%hCGPj$3%0{e;``>D7TlmL%Wpg zp3Q??11yPh8Zb@=m;ulSAU@JF@!54Om@t6bwTHVeGwEMSDwEe<*khNH$zzaZ*!`>4 zdg_C6srHM!;dbV^O#4gT_=s1DDQj&nu3BfmiC?T7Onf+psPf=|Q{O)o4HrP@n{)5Noyqo{N|3!#o$ z)68L#e3WJi4ks{4hEPo<#!4HThd!;js6;%i-BmPo7VB&x>1=iNjOxSouCnB@W2~1I zBZ~lFuU6Qr&J^Pc?Z#ejEq8&E)dUQy>JGYD7|!JXEGM}Zjn)A`2?EIkVseR?5bbF1 z-r}V8TJNbOmDFNSzr&*1sdV68qGcC$_ZANluV^QW2e4|(AbMy4=&BYQkO}ZhExpfD zlOLMfTl2IV`_$&RsladqJVDobk6h≻qPULZ6~MwybH*((8+tv{BvHwE=x66Paq? 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 diff --git a/litellm/llms/ai21.py b/litellm/llms/ai21.py index 3bf4c1004..6991dcedf 100644 --- a/litellm/llms/ai21.py +++ b/litellm/llms/ai21.py @@ -1,10 +1,10 @@ -import os, types +import os, types, traceback import json from enum import Enum import requests import time from typing import Callable, Optional -from litellm.utils import ModelResponse +from litellm.utils import ModelResponse, Choices, Message import litellm class AI21Error(Exception): @@ -159,10 +159,14 @@ def completion( ) else: try: - model_response["choices"][0]["message"]["content"] = completion_response["completions"][0]["data"]["text"] - model_response.choices[0].finish_reason = completion_response["completions"][0]["finishReason"]["reason"] + choices_list = [] + for idx, item in enumerate(completion_response["completions"]): + message_obj = Message(content=item["data"]["text"]) + choice_obj = Choices(finish_reason=item["finishReason"]["reason"], index=idx+1, message=message_obj) + choices_list.append(choice_obj) + model_response["choices"] = choices_list except Exception as e: - raise AI21Error(message=json.dumps(completion_response), status_code=response.status_code) + raise AI21Error(message=traceback.format_exc(), status_code=response.status_code) ## CALCULATING USAGE - baseten charges on time, not tokens - have some mapping of cost here. prompt_tokens = len( diff --git a/litellm/llms/cohere.py b/litellm/llms/cohere.py index dbd0c0ea8..8b4bed061 100644 --- a/litellm/llms/cohere.py +++ b/litellm/llms/cohere.py @@ -2,9 +2,9 @@ import os, types import json from enum import Enum import requests -import time +import time, traceback from typing import Callable, Optional -from litellm.utils import ModelResponse +from litellm.utils import ModelResponse, Choices, Message import litellm class CohereError(Exception): @@ -156,11 +156,16 @@ def completion( ) else: try: - model_response["choices"][0]["message"]["content"] = completion_response["generations"][0]["text"] - except: - raise CohereError(message=json.dumps(completion_response), status_code=response.status_code) + choices_list = [] + for idx, item in enumerate(completion_response["generations"]): + message_obj = Message(content=item["text"]) + choice_obj = Choices(finish_reason=item["finish_reason"], index=idx+1, message=message_obj) + choices_list.append(choice_obj) + model_response["choices"] = choices_list + except Exception as e: + raise CohereError(message=traceback.format_exc(), status_code=response.status_code) - ## CALCULATING USAGE - baseten charges on time, not tokens - have some mapping of cost here. + ## CALCULATING USAGE prompt_tokens = len( encoding.encode(prompt) ) diff --git a/litellm/llms/palm.py b/litellm/llms/palm.py index 21e1f5542..5205a6cb5 100644 --- a/litellm/llms/palm.py +++ b/litellm/llms/palm.py @@ -1,9 +1,9 @@ -import os, types +import os, types, traceback import json from enum import Enum import time from typing import Callable, Optional -from litellm.utils import ModelResponse, get_secret +from litellm.utils import ModelResponse, get_secret, Choices, Message import litellm import sys @@ -33,7 +33,7 @@ class PalmConfig(): - `top_p` (float): The API uses combined nucleus and top-k sampling. `top_p` configures the nucleus sampling. It sets the maximum cumulative probability of tokens to sample from. - - `maxOutputTokens` (int): Sets the maximum number of tokens to be returned in the output + - `max_output_tokens` (int): Sets the maximum number of tokens to be returned in the output """ context: Optional[str]=None examples: Optional[list]=None @@ -41,7 +41,7 @@ class PalmConfig(): candidate_count: Optional[int]=None top_k: Optional[int]=None top_p: Optional[float]=None - maxOutputTokens: Optional[int]=None + max_output_tokens: Optional[int]=None def __init__(self, context: Optional[str]=None, @@ -50,7 +50,7 @@ class PalmConfig(): candidate_count: Optional[int]=None, top_k: Optional[int]=None, top_p: Optional[float]=None, - maxOutputTokens: Optional[int]=None) -> None: + max_output_tokens: Optional[int]=None) -> None: locals_ = locals() for key, value in locals_.items(): @@ -110,10 +110,16 @@ def completion( logging_obj.pre_call( input=prompt, api_key="", - additional_args={"complete_input_dict": {}}, + additional_args={"complete_input_dict": {"optional_params": optional_params}}, ) ## COMPLETION CALL - response = palm.chat(messages=prompt) + try: + response = palm.generate_text(prompt=prompt, **optional_params) + except Exception as e: + raise PalmError( + message=str(e), + status_code=500, + ) ## LOGGING logging_obj.post_call( @@ -124,18 +130,17 @@ def completion( ) print_verbose(f"raw model_response: {response}") ## RESPONSE OBJECT - completion_response = response.last - - if "error" in completion_response: - raise PalmError( - message=completion_response["error"], - status_code=response.status_code, - ) - else: - try: - model_response["choices"][0]["message"]["content"] = completion_response - except: - raise PalmError(message=json.dumps(completion_response), status_code=response.status_code) + completion_response = response + try: + choices_list = [] + for idx, item in enumerate(completion_response.candidates): + message_obj = Message(content=item["output"]) + choice_obj = Choices(index=idx+1, message=message_obj) + choices_list.append(choice_obj) + model_response["choices"] = choices_list + except Exception as e: + traceback.print_exc() + raise PalmError(message=traceback.format_exc(), status_code=response.status_code) ## CALCULATING USAGE - baseten charges on time, not tokens - have some mapping of cost here. prompt_tokens = len( diff --git a/litellm/llms/together_ai.py b/litellm/llms/together_ai.py index e5b583524..6a134e2bd 100644 --- a/litellm/llms/together_ai.py +++ b/litellm/llms/together_ai.py @@ -161,7 +161,7 @@ def completion( raise TogetherAIError( message=json.dumps(completion_response["output"]), status_code=response.status_code ) - + completion_text = completion_response["output"]["choices"][0]["text"] ## CALCULATING USAGE - baseten charges on time, not tokens - have some mapping of cost here. diff --git a/litellm/tests/test_provider_specific_config.py b/litellm/tests/test_provider_specific_config.py index bc4bef506..9cf7ecb04 100644 --- a/litellm/tests/test_provider_specific_config.py +++ b/litellm/tests/test_provider_specific_config.py @@ -50,7 +50,7 @@ def claude_test_completion(): try: # OVERRIDE WITH DYNAMIC MAX TOKENS response_1 = litellm.completion( - model="together_ai/togethercomputer/llama-2-70b-chat", + model="claude-instant-1", messages=[{ "content": "Hello, how are you?","role": "user"}], max_tokens=10 ) @@ -60,7 +60,7 @@ def claude_test_completion(): # USE CONFIG TOKENS response_2 = litellm.completion( - model="together_ai/togethercomputer/llama-2-70b-chat", + model="claude-instant-1", messages=[{ "content": "Hello, how are you?","role": "user"}], ) # Add any assertions here to check the response @@ -68,6 +68,14 @@ def claude_test_completion(): response_2_text = response_2.choices[0].message.content assert len(response_2_text) > len(response_1_text) + + try: + response_3 = litellm.completion(model="claude-instant-1", + messages=[{ "content": "Hello, how are you?","role": "user"}], + n=2) + + except Exception as e: + print(e) except Exception as e: pytest.fail(f"Error occurred: {e}") @@ -99,6 +107,12 @@ def replicate_test_completion(): response_2_text = response_2.choices[0].message.content assert len(response_2_text) > len(response_1_text) + try: + response_3 = litellm.completion(model="meta/llama-2-70b-chat:02e509c789964a7ea8736978a43525956ef40397be9033abf9fd2badfe68c9e3", + messages=[{ "content": "Hello, how are you?","role": "user"}], + n=2) + except: + pass except Exception as e: pytest.fail(f"Error occurred: {e}") @@ -107,8 +121,8 @@ def replicate_test_completion(): # Cohere def cohere_test_completion(): - litellm.CohereConfig(max_tokens=200) - # litellm.set_verbose=True + # litellm.CohereConfig(max_tokens=200) + litellm.set_verbose=True try: # OVERRIDE WITH DYNAMIC MAX TOKENS response_1 = litellm.completion( @@ -126,6 +140,11 @@ def cohere_test_completion(): response_2_text = response_2.choices[0].message.content assert len(response_2_text) > len(response_1_text) + + response_3 = litellm.completion(model="command-nightly", + messages=[{ "content": "Hello, how are you?","role": "user"}], + n=2) + assert len(response_3.choices) > 1 except Exception as e: pytest.fail(f"Error occurred: {e}") @@ -135,7 +154,7 @@ def cohere_test_completion(): def ai21_test_completion(): litellm.AI21Config(maxTokens=10) - # litellm.set_verbose=True + litellm.set_verbose=True try: # OVERRIDE WITH DYNAMIC MAX TOKENS response_1 = litellm.completion( @@ -155,6 +174,11 @@ def ai21_test_completion(): print(f"response_2_text: {response_2_text}") assert len(response_2_text) < len(response_1_text) + + response_3 = litellm.completion(model="j2-light", + messages=[{ "content": "Hello, how are you?","role": "user"}], + n=2) + assert len(response_3.choices) > 1 except Exception as e: pytest.fail(f"Error occurred: {e}") @@ -164,7 +188,7 @@ def ai21_test_completion(): def togetherai_test_completion(): litellm.TogetherAIConfig(max_tokens=10) - # litellm.set_verbose=True + litellm.set_verbose=True try: # OVERRIDE WITH DYNAMIC MAX TOKENS response_1 = litellm.completion( @@ -184,6 +208,14 @@ def togetherai_test_completion(): print(f"response_2_text: {response_2_text}") assert len(response_2_text) < len(response_1_text) + + try: + response_3 = litellm.completion(model="together_ai/togethercomputer/llama-2-70b-chat", + messages=[{ "content": "Hello, how are you?","role": "user"}], + n=2) + pytest.fail(f"Error not raised when n=2 passed to provider") + except: + pass except Exception as e: pytest.fail(f"Error occurred: {e}") @@ -192,7 +224,7 @@ def togetherai_test_completion(): # Palm def palm_test_completion(): - litellm.PalmConfig(maxOutputTokens=10) + litellm.PalmConfig(max_output_tokens=10, temperature=0.9) # litellm.set_verbose=True try: # OVERRIDE WITH DYNAMIC MAX TOKENS @@ -213,6 +245,11 @@ def palm_test_completion(): print(f"response_2_text: {response_2_text}") assert len(response_2_text) < len(response_1_text) + + response_3 = litellm.completion(model="palm/chat-bison", + messages=[{ "content": "Hello, how are you?","role": "user"}], + n=2) + assert len(response_3.choices) > 1 except Exception as e: pytest.fail(f"Error occurred: {e}") @@ -242,6 +279,14 @@ def nlp_cloud_test_completion(): print(f"response_2_text: {response_2_text}") assert len(response_2_text) < len(response_1_text) + + try: + response_3 = litellm.completion(model="dolphin", + messages=[{ "content": "Hello, how are you?","role": "user"}], + n=2) + pytest.fail(f"Error not raised when n=2 passed to provider") + except: + pass except Exception as e: pytest.fail(f"Error occurred: {e}") @@ -271,6 +316,14 @@ def aleph_alpha_test_completion(): print(f"response_2_text: {response_2_text}") assert len(response_2_text) < len(response_1_text) + + try: + response_3 = litellm.completion(model="luminous-base", + messages=[{ "content": "Hello, how are you?","role": "user"}], + n=2) + pytest.fail(f"Error not raised when n=2 passed to provider") + except: + pass except Exception as e: pytest.fail(f"Error occurred: {e}") diff --git a/litellm/utils.py b/litellm/utils.py index 3bdf51918..a4ffa7918 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -97,6 +97,15 @@ last_fetched_at_keys = None # 'usage': {'prompt_tokens': 18, 'completion_tokens': 23, 'total_tokens': 41} # } +class UnsupportedParamsError(Exception): + def __init__(self, status_code, message): + self.status_code = status_code + self.message = message + super().__init__( + self.message + ) # Call the base class constructor with the parameters it needs + + def _generate_id(): # private helper function return 'chatcmpl-' + str(uuid.uuid4()) @@ -1008,7 +1017,7 @@ def get_optional_params( # use the openai defaults if litellm.add_function_to_prompt: # if user opts to add it to prompt instead optional_params["functions_unsupported_model"] = non_default_params.pop("functions") else: - raise ValueError(f"LiteLLM.Exception: Function calling is not supported by {custom_llm_provider}. To add it to the prompt, set `litellm.add_function_to_prompt = True`.") + raise UnsupportedParamsError(status_code=500, message=f"Function calling is not supported by {custom_llm_provider}. To add it to the prompt, set `litellm.add_function_to_prompt = True`.") def _check_valid_arg(supported_params): print_verbose(f"checking params for {model}") @@ -1025,7 +1034,7 @@ def get_optional_params( # use the openai defaults else: unsupported_params[k] = non_default_params[k] if unsupported_params and not litellm.drop_params: - raise ValueError(f"LiteLLM.Exception: {custom_llm_provider} does not support parameters: {unsupported_params}. To drop these, set `litellm.drop_params=True`.") + raise UnsupportedParamsError(status_code=500, message=f"{custom_llm_provider} does not support parameters: {unsupported_params}. To drop these, set `litellm.drop_params=True`.") ## raise exception if provider doesn't support passed in param if custom_llm_provider == "anthropic": @@ -1163,7 +1172,7 @@ def get_optional_params( # use the openai defaults if stop: optional_params["stopSequences"] = stop if max_tokens: - optional_params["maxOutputTokens"] = max_tokens + optional_params["max_output_tokens"] = max_tokens elif ( custom_llm_provider == "vertex_ai" ):