diff options
author | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
---|---|---|
committer | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
commit | 4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch) | |
tree | ee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/litellm/llms/openai/completion | |
parent | cc961e04ba734dd72309fb548a2f97d67d578813 (diff) | |
download | gn-ai-master.tar.gz |
Diffstat (limited to '.venv/lib/python3.12/site-packages/litellm/llms/openai/completion')
3 files changed, 527 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/litellm/llms/openai/completion/handler.py b/.venv/lib/python3.12/site-packages/litellm/llms/openai/completion/handler.py new file mode 100644 index 00000000..2e60f55b --- /dev/null +++ b/.venv/lib/python3.12/site-packages/litellm/llms/openai/completion/handler.py @@ -0,0 +1,319 @@ +import json +from typing import Callable, List, Optional, Union + +from openai import AsyncOpenAI, OpenAI + +import litellm +from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj +from litellm.litellm_core_utils.streaming_handler import CustomStreamWrapper +from litellm.llms.base import BaseLLM +from litellm.types.llms.openai import AllMessageValues, OpenAITextCompletionUserMessage +from litellm.types.utils import LlmProviders, ModelResponse, TextCompletionResponse +from litellm.utils import ProviderConfigManager + +from ..common_utils import OpenAIError +from .transformation import OpenAITextCompletionConfig + + +class OpenAITextCompletion(BaseLLM): + openai_text_completion_global_config = OpenAITextCompletionConfig() + + def __init__(self) -> None: + super().__init__() + + def validate_environment(self, api_key): + headers = { + "content-type": "application/json", + } + if api_key: + headers["Authorization"] = f"Bearer {api_key}" + return headers + + def completion( + self, + model_response: ModelResponse, + api_key: str, + model: str, + messages: Union[List[AllMessageValues], List[OpenAITextCompletionUserMessage]], + timeout: float, + custom_llm_provider: str, + logging_obj: LiteLLMLoggingObj, + optional_params: dict, + print_verbose: Optional[Callable] = None, + api_base: Optional[str] = None, + acompletion: bool = False, + litellm_params=None, + logger_fn=None, + client=None, + organization: Optional[str] = None, + headers: Optional[dict] = None, + ): + try: + if headers is None: + headers = self.validate_environment(api_key=api_key) + if model is None or messages is None: + raise OpenAIError(status_code=422, message="Missing model or messages") + + # don't send max retries to the api, if set + + provider_config = ProviderConfigManager.get_provider_text_completion_config( + model=model, + provider=LlmProviders(custom_llm_provider), + ) + + data = provider_config.transform_text_completion_request( + model=model, + messages=messages, + optional_params=optional_params, + headers=headers, + ) + max_retries = data.pop("max_retries", 2) + ## LOGGING + logging_obj.pre_call( + input=messages, + api_key=api_key, + additional_args={ + "headers": headers, + "api_base": api_base, + "complete_input_dict": data, + }, + ) + if acompletion is True: + if optional_params.get("stream", False): + return self.async_streaming( + logging_obj=logging_obj, + api_base=api_base, + api_key=api_key, + data=data, + headers=headers, + model_response=model_response, + model=model, + timeout=timeout, + max_retries=max_retries, + client=client, + organization=organization, + ) + else: + return self.acompletion(api_base=api_base, data=data, headers=headers, model_response=model_response, api_key=api_key, logging_obj=logging_obj, model=model, timeout=timeout, max_retries=max_retries, organization=organization, client=client) # type: ignore + elif optional_params.get("stream", False): + return self.streaming( + logging_obj=logging_obj, + api_base=api_base, + api_key=api_key, + data=data, + headers=headers, + model_response=model_response, + model=model, + timeout=timeout, + max_retries=max_retries, # type: ignore + client=client, + organization=organization, + ) + else: + if client is None: + openai_client = OpenAI( + api_key=api_key, + base_url=api_base, + http_client=litellm.client_session, + timeout=timeout, + max_retries=max_retries, # type: ignore + organization=organization, + ) + else: + openai_client = client + + raw_response = openai_client.completions.with_raw_response.create(**data) # type: ignore + response = raw_response.parse() + response_json = response.model_dump() + + ## LOGGING + logging_obj.post_call( + api_key=api_key, + original_response=response_json, + additional_args={ + "headers": headers, + "api_base": api_base, + }, + ) + + ## RESPONSE OBJECT + return TextCompletionResponse(**response_json) + except Exception as e: + status_code = getattr(e, "status_code", 500) + error_headers = getattr(e, "headers", None) + error_text = getattr(e, "text", str(e)) + error_response = getattr(e, "response", None) + if error_headers is None and error_response: + error_headers = getattr(error_response, "headers", None) + raise OpenAIError( + status_code=status_code, message=error_text, headers=error_headers + ) + + async def acompletion( + self, + logging_obj, + api_base: str, + data: dict, + headers: dict, + model_response: ModelResponse, + api_key: str, + model: str, + timeout: float, + max_retries: int, + organization: Optional[str] = None, + client=None, + ): + try: + if client is None: + openai_aclient = AsyncOpenAI( + api_key=api_key, + base_url=api_base, + http_client=litellm.aclient_session, + timeout=timeout, + max_retries=max_retries, + organization=organization, + ) + else: + openai_aclient = client + + raw_response = await openai_aclient.completions.with_raw_response.create( + **data + ) + response = raw_response.parse() + response_json = response.model_dump() + + ## LOGGING + logging_obj.post_call( + api_key=api_key, + original_response=response, + additional_args={ + "headers": headers, + "api_base": api_base, + }, + ) + ## RESPONSE OBJECT + response_obj = TextCompletionResponse(**response_json) + response_obj._hidden_params.original_response = json.dumps(response_json) + return response_obj + except Exception as e: + status_code = getattr(e, "status_code", 500) + error_headers = getattr(e, "headers", None) + error_text = getattr(e, "text", str(e)) + error_response = getattr(e, "response", None) + if error_headers is None and error_response: + error_headers = getattr(error_response, "headers", None) + raise OpenAIError( + status_code=status_code, message=error_text, headers=error_headers + ) + + def streaming( + self, + logging_obj, + api_key: str, + data: dict, + headers: dict, + model_response: ModelResponse, + model: str, + timeout: float, + api_base: Optional[str] = None, + max_retries=None, + client=None, + organization=None, + ): + + if client is None: + openai_client = OpenAI( + api_key=api_key, + base_url=api_base, + http_client=litellm.client_session, + timeout=timeout, + max_retries=max_retries, # type: ignore + organization=organization, + ) + else: + openai_client = client + + try: + raw_response = openai_client.completions.with_raw_response.create(**data) + response = raw_response.parse() + except Exception as e: + status_code = getattr(e, "status_code", 500) + error_headers = getattr(e, "headers", None) + error_text = getattr(e, "text", str(e)) + error_response = getattr(e, "response", None) + if error_headers is None and error_response: + error_headers = getattr(error_response, "headers", None) + raise OpenAIError( + status_code=status_code, message=error_text, headers=error_headers + ) + streamwrapper = CustomStreamWrapper( + completion_stream=response, + model=model, + custom_llm_provider="text-completion-openai", + logging_obj=logging_obj, + stream_options=data.get("stream_options", None), + ) + + try: + for chunk in streamwrapper: + yield chunk + except Exception as e: + status_code = getattr(e, "status_code", 500) + error_headers = getattr(e, "headers", None) + error_text = getattr(e, "text", str(e)) + error_response = getattr(e, "response", None) + if error_headers is None and error_response: + error_headers = getattr(error_response, "headers", None) + raise OpenAIError( + status_code=status_code, message=error_text, headers=error_headers + ) + + async def async_streaming( + self, + logging_obj, + api_key: str, + data: dict, + headers: dict, + model_response: ModelResponse, + model: str, + timeout: float, + max_retries: int, + api_base: Optional[str] = None, + client=None, + organization=None, + ): + if client is None: + openai_client = AsyncOpenAI( + api_key=api_key, + base_url=api_base, + http_client=litellm.aclient_session, + timeout=timeout, + max_retries=max_retries, + organization=organization, + ) + else: + openai_client = client + + raw_response = await openai_client.completions.with_raw_response.create(**data) + response = raw_response.parse() + streamwrapper = CustomStreamWrapper( + completion_stream=response, + model=model, + custom_llm_provider="text-completion-openai", + logging_obj=logging_obj, + stream_options=data.get("stream_options", None), + ) + + try: + async for transformed_chunk in streamwrapper: + yield transformed_chunk + except Exception as e: + status_code = getattr(e, "status_code", 500) + error_headers = getattr(e, "headers", None) + error_text = getattr(e, "text", str(e)) + error_response = getattr(e, "response", None) + if error_headers is None and error_response: + error_headers = getattr(error_response, "headers", None) + raise OpenAIError( + status_code=status_code, message=error_text, headers=error_headers + ) diff --git a/.venv/lib/python3.12/site-packages/litellm/llms/openai/completion/transformation.py b/.venv/lib/python3.12/site-packages/litellm/llms/openai/completion/transformation.py new file mode 100644 index 00000000..1aef72d3 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/litellm/llms/openai/completion/transformation.py @@ -0,0 +1,158 @@ +""" +Support for gpt model family +""" + +from typing import List, Optional, Union + +from litellm.llms.base_llm.completion.transformation import BaseTextCompletionConfig +from litellm.types.llms.openai import AllMessageValues, OpenAITextCompletionUserMessage +from litellm.types.utils import Choices, Message, ModelResponse, TextCompletionResponse + +from ..chat.gpt_transformation import OpenAIGPTConfig +from .utils import _transform_prompt + + +class OpenAITextCompletionConfig(BaseTextCompletionConfig, OpenAIGPTConfig): + """ + Reference: https://platform.openai.com/docs/api-reference/completions/create + + The class `OpenAITextCompletionConfig` provides configuration for the OpenAI's text completion API interface. Below are the parameters: + + - `best_of` (integer or null): This optional parameter generates server-side completions and returns the one with the highest log probability per token. + + - `echo` (boolean or null): This optional parameter will echo back the prompt in addition to the completion. + + - `frequency_penalty` (number or null): Defaults to 0. It is a numbers from -2.0 to 2.0, where positive values decrease the model's likelihood to repeat the same line. + + - `logit_bias` (map): This optional parameter modifies the likelihood of specified tokens appearing in the completion. + + - `logprobs` (integer or null): This optional parameter includes the log probabilities on the most likely tokens as well as the chosen tokens. + + - `max_tokens` (integer or null): This optional parameter sets the maximum number of tokens to generate in the completion. + + - `n` (integer or null): This optional parameter sets how many completions to generate for each prompt. + + - `presence_penalty` (number or null): Defaults to 0 and can be between -2.0 and 2.0. Positive values increase the model's likelihood to talk about new topics. + + - `stop` (string / array / null): Specifies up to 4 sequences where the API will stop generating further tokens. + + - `suffix` (string or null): Defines the suffix that comes after a completion of inserted text. + + - `temperature` (number or null): This optional parameter defines the sampling temperature to use. + + - `top_p` (number or null): An alternative to sampling with temperature, used for nucleus sampling. + """ + + best_of: Optional[int] = None + echo: Optional[bool] = None + frequency_penalty: Optional[int] = None + logit_bias: Optional[dict] = None + logprobs: Optional[int] = None + max_tokens: Optional[int] = None + n: Optional[int] = None + presence_penalty: Optional[int] = None + stop: Optional[Union[str, list]] = None + suffix: Optional[str] = None + + def __init__( + self, + best_of: Optional[int] = None, + echo: Optional[bool] = None, + frequency_penalty: Optional[int] = None, + logit_bias: Optional[dict] = None, + logprobs: Optional[int] = None, + max_tokens: Optional[int] = None, + n: Optional[int] = None, + presence_penalty: Optional[int] = None, + stop: Optional[Union[str, list]] = None, + suffix: Optional[str] = None, + temperature: Optional[float] = None, + top_p: Optional[float] = None, + ) -> None: + locals_ = locals().copy() + for key, value in locals_.items(): + if key != "self" and value is not None: + setattr(self.__class__, key, value) + + @classmethod + def get_config(cls): + return super().get_config() + + def convert_to_chat_model_response_object( + self, + response_object: Optional[TextCompletionResponse] = None, + model_response_object: Optional[ModelResponse] = None, + ): + try: + ## RESPONSE OBJECT + if response_object is None or model_response_object is None: + raise ValueError("Error in response object format") + choice_list = [] + for idx, choice in enumerate(response_object["choices"]): + message = Message( + content=choice["text"], + role="assistant", + ) + choice = Choices( + finish_reason=choice["finish_reason"], + index=idx, + message=message, + logprobs=choice.get("logprobs", None), + ) + choice_list.append(choice) + model_response_object.choices = choice_list + + if "usage" in response_object: + setattr(model_response_object, "usage", response_object["usage"]) + + if "id" in response_object: + model_response_object.id = response_object["id"] + + if "model" in response_object: + model_response_object.model = response_object["model"] + + model_response_object._hidden_params["original_response"] = ( + response_object # track original response, if users make a litellm.text_completion() request, we can return the original response + ) + return model_response_object + except Exception as e: + raise e + + def get_supported_openai_params(self, model: str) -> List: + return [ + "functions", + "function_call", + "temperature", + "top_p", + "n", + "stream", + "stream_options", + "stop", + "max_tokens", + "presence_penalty", + "frequency_penalty", + "logit_bias", + "user", + "response_format", + "seed", + "tools", + "tool_choice", + "max_retries", + "logprobs", + "top_logprobs", + "extra_headers", + ] + + def transform_text_completion_request( + self, + model: str, + messages: Union[List[AllMessageValues], List[OpenAITextCompletionUserMessage]], + optional_params: dict, + headers: dict, + ) -> dict: + prompt = _transform_prompt(messages) + return { + "model": model, + "prompt": prompt, + **optional_params, + } diff --git a/.venv/lib/python3.12/site-packages/litellm/llms/openai/completion/utils.py b/.venv/lib/python3.12/site-packages/litellm/llms/openai/completion/utils.py new file mode 100644 index 00000000..8b3efb4c --- /dev/null +++ b/.venv/lib/python3.12/site-packages/litellm/llms/openai/completion/utils.py @@ -0,0 +1,50 @@ +from typing import List, Union, cast + +from litellm.litellm_core_utils.prompt_templates.common_utils import ( + convert_content_list_to_str, +) +from litellm.types.llms.openai import ( + AllMessageValues, + AllPromptValues, + OpenAITextCompletionUserMessage, +) + + +def is_tokens_or_list_of_tokens(value: List): + # Check if it's a list of integers (tokens) + if isinstance(value, list) and all(isinstance(item, int) for item in value): + return True + # Check if it's a list of lists of integers (list of tokens) + if isinstance(value, list) and all( + isinstance(item, list) and all(isinstance(i, int) for i in item) + for item in value + ): + return True + return False + + +def _transform_prompt( + messages: Union[List[AllMessageValues], List[OpenAITextCompletionUserMessage]], +) -> AllPromptValues: + if len(messages) == 1: # base case + message_content = messages[0].get("content") + if ( + message_content + and isinstance(message_content, list) + and is_tokens_or_list_of_tokens(message_content) + ): + openai_prompt: AllPromptValues = cast(AllPromptValues, message_content) + else: + openai_prompt = "" + content = convert_content_list_to_str(cast(AllMessageValues, messages[0])) + openai_prompt += content + else: + prompt_str_list: List[str] = [] + for m in messages: + try: # expect list of int/list of list of int to be a 1 message array only. + content = convert_content_list_to_str(cast(AllMessageValues, m)) + prompt_str_list.append(content) + except Exception as e: + raise e + openai_prompt = prompt_str_list + return openai_prompt |