diff --git a/litellm/__init__.py b/litellm/__init__.py index 933a6ca8af..73257a8bce 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -1,7 +1,7 @@ success_callback = [] failure_callback = [] set_verbose=False - +telemetry=True ####### COMPLETION MODELS ################### open_ai_chat_completion_models = [ 'gpt-3.5-turbo', diff --git a/litellm/__pycache__/__init__.cpython-311.pyc b/litellm/__pycache__/__init__.cpython-311.pyc index 6dd968755a..e487c18c97 100644 Binary files a/litellm/__pycache__/__init__.cpython-311.pyc and b/litellm/__pycache__/__init__.cpython-311.pyc differ diff --git a/litellm/__pycache__/main.cpython-311.pyc b/litellm/__pycache__/main.cpython-311.pyc index 21e92f305d..153207bb97 100644 Binary files a/litellm/__pycache__/main.cpython-311.pyc and b/litellm/__pycache__/main.cpython-311.pyc differ diff --git a/litellm/__pycache__/timeout.cpython-311.pyc b/litellm/__pycache__/timeout.cpython-311.pyc index 8524f017a8..880e08abbb 100644 Binary files a/litellm/__pycache__/timeout.cpython-311.pyc and b/litellm/__pycache__/timeout.cpython-311.pyc differ diff --git a/litellm/__pycache__/utils.cpython-311.pyc b/litellm/__pycache__/utils.cpython-311.pyc index 71c54c1834..0d9aacf693 100644 Binary files a/litellm/__pycache__/utils.cpython-311.pyc and b/litellm/__pycache__/utils.cpython-311.pyc differ diff --git a/litellm/main.py b/litellm/main.py index c17c5d402b..a90c9bf81f 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -252,35 +252,40 @@ def completion( @client @timeout(60) ## set timeouts, in case calls hang (e.g. Azure) - default is 60s, override with `force_timeout` def embedding(model, input=[], azure=False, force_timeout=60, logger_fn=None): - response = None - if azure == True: - # azure configs - openai.api_type = "azure" - openai.api_base = os.environ.get("AZURE_API_BASE") - openai.api_version = os.environ.get("AZURE_API_VERSION") - openai.api_key = os.environ.get("AZURE_API_KEY") - ## LOGGING - logging(model=model, input=input, azure=azure, logger_fn=logger_fn) - ## EMBEDDING CALL - response = openai.Embedding.create(input=input, engine=model) - print_verbose(f"response_value: {str(response)[:50]}") - elif model in litellm.open_ai_embedding_models: - openai.api_type = "openai" - openai.api_base = "https://api.openai.com/v1" - openai.api_version = None - openai.api_key = os.environ.get("OPENAI_API_KEY") - ## LOGGING - logging(model=model, input=input, azure=azure, logger_fn=logger_fn) - ## EMBEDDING CALL - response = openai.Embedding.create(input=input, model=model) - print_verbose(f"response_value: {str(response)[:50]}") - else: - logging(model=model, input=input, azure=azure, logger_fn=logger_fn) - args = locals() - raise ValueError(f"No valid embedding model args passed in - {args}") - - return response - + try: + response = None + if azure == True: + # azure configs + openai.api_type = "azure" + openai.api_base = os.environ.get("AZURE_API_BASE") + openai.api_version = os.environ.get("AZURE_API_VERSION") + openai.api_key = os.environ.get("AZURE_API_KEY") + ## LOGGING + logging(model=model, input=input, azure=azure, logger_fn=logger_fn) + ## EMBEDDING CALL + response = openai.Embedding.create(input=input, engine=model) + print_verbose(f"response_value: {str(response)[:50]}") + elif model in litellm.open_ai_embedding_models: + openai.api_type = "openai" + openai.api_base = "https://api.openai.com/v1" + openai.api_version = None + openai.api_key = os.environ.get("OPENAI_API_KEY") + ## LOGGING + logging(model=model, input=input, azure=azure, logger_fn=logger_fn) + ## EMBEDDING CALL + response = openai.Embedding.create(input=input, model=model) + print_verbose(f"response_value: {str(response)[:50]}") + else: + logging(model=model, input=input, azure=azure, logger_fn=logger_fn) + args = locals() + raise ValueError(f"No valid embedding model args passed in - {args}") + + return response + except Exception as e: + # log the original exception + logging(model=model, input=input, azure=azure, logger_fn=logger_fn, exception=e) + ## Map to OpenAI Exception + raise exception_type(model=model, original_exception=e) ####### HELPER FUNCTIONS ################ ## Set verbose to true -> ```litellm.set_verbose = True``` def print_verbose(print_statement): diff --git a/litellm/tests/litellm_uuid.txt b/litellm/tests/litellm_uuid.txt new file mode 100644 index 0000000000..e4252e46d0 --- /dev/null +++ b/litellm/tests/litellm_uuid.txt @@ -0,0 +1 @@ +80888ede-4881-4876-ab3f-765d47282e66 \ No newline at end of file diff --git a/litellm/utils.py b/litellm/utils.py index d590318754..e2b4f56554 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -1,14 +1,7 @@ -import dotenv -import json -import traceback -import threading -import traceback -import subprocess -import uuid -import litellm -import os -import openai -import random +import dotenv, json, traceback, threading +import subprocess, os +import litellm, openai +import random, uuid, requests from openai.error import AuthenticationError, InvalidRequestError, RateLimitError, ServiceUnavailableError, OpenAIError ####### ENVIRONMENT VARIABLES ################### dotenv.load_dotenv() # Loading env variables using dotenv @@ -34,11 +27,15 @@ def logging(model, input, azure=False, additional_args={}, logger_fn=None, excep try: model_call_details = {} model_call_details["model"] = model - model_call_details["input"] = input model_call_details["azure"] = azure # log exception details if exception: model_call_details["original_exception"] = exception + + if litellm.telemetry: + safe_crash_reporting(model=model, exception=exception, azure=azure) # log usage-crash details. Do not log any user details. If you want to turn this off, set `litellm.telemetry=False`. + + model_call_details["input"] = input # log additional call details -> api key, etc. if azure == True or model in litellm.open_ai_chat_completion_models or model in litellm.open_ai_chat_completion_models or model in litellm.open_ai_embedding_models: model_call_details["api_type"] = openai.api_type @@ -273,4 +270,48 @@ def exception_type(model, original_exception): raise original_exception # base case - return the original exception else: raise original_exception - \ No newline at end of file + +def safe_crash_reporting(model=None, exception=None, azure=None): + data = { + "model": model, + "exception": str(exception), + "azure": azure + } + print(f"data in crash reporting: {data}") + threading.Thread(target=litellm_telemetry, args=(data,), daemon=True).start() + +def litellm_telemetry(data): + print(f"data in in litellm telemetry: {data}") + # Load or generate the UUID + uuid_file = 'litellm_uuid.txt' + try: + # Try to open the file and load the UUID + with open(uuid_file, 'r') as file: + uuid_value = file.read() + if uuid_value: + uuid_value = uuid_value.strip() + print(f"Loaded UUID: {uuid_value}") + else: + raise FileNotFoundError + except FileNotFoundError: + # Generate a new UUID if the file doesn't exist or is empty + new_uuid = uuid.uuid4() + uuid_value = str(new_uuid) + with open(uuid_file, 'w') as file: + file.write(uuid_value) + print(f"Generated and stored UUID: {uuid_value}") + + # Prepare the data to send to localhost:3000 + payload = { + 'uuid': uuid_value, + 'data': data + } + print_verbose(f"payload: {payload}") + try: + # Make the POST request to localhost:3000 + response = requests.post('https://litellm.berri.ai/logging', json=payload) + response.raise_for_status() # Raise an exception for HTTP errors + print('Request successfully sent!') + except requests.exceptions.RequestException as e: + # Handle any errors in the request + print(f'Error: {e}') \ No newline at end of file