diff --git a/README.md b/README.md index 8b2f9cce3..47a584e69 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@

Call all LLM APIs using the OpenAI format [Bedrock, Huggingface, VertexAI, TogetherAI, Azure, OpenAI, etc.]

-

OpenAI Proxy Server | Enterprise Support

+

OpenAI Proxy Server | Enterprise Tier

PyPI Version @@ -28,7 +28,7 @@ LiteLLM manages: - Translate inputs to provider's `completion`, `embedding`, and `image_generation` endpoints - [Consistent output](https://docs.litellm.ai/docs/completion/output), text responses will always be available at `['choices'][0]['message']['content']` - Retry/fallback logic across multiple deployments (e.g. Azure/OpenAI) - [Router](https://docs.litellm.ai/docs/routing) -- Track spend & set budgets per project [OpenAI Proxy Server](https://docs.litellm.ai/docs/simple_proxy) +- Set Budgets & Rate limits per project [OpenAI Proxy Server](https://docs.litellm.ai/docs/simple_proxy) [**Jump to OpenAI Proxy Docs**](https://github.com/BerriAI/litellm?tab=readme-ov-file#openai-proxy---docs)
diff --git a/docs/my-website/docs/proxy/logging.md b/docs/my-website/docs/proxy/logging.md index 0c5fd6bb9..3f5596fc9 100644 --- a/docs/my-website/docs/proxy/logging.md +++ b/docs/my-website/docs/proxy/logging.md @@ -8,6 +8,7 @@ import TabItem from '@theme/TabItem'; Log Proxy Input, Output, Exceptions using Custom Callbacks, Langfuse, OpenTelemetry, LangFuse, DynamoDB, s3 Bucket - [Async Custom Callbacks](#custom-callback-class-async) +- [Async Custom Callback APIs](#custom-callback-apis-async) - [Logging to Langfuse](#logging-proxy-inputoutput---langfuse) - [Logging to s3 Buckets](#logging-proxy-inputoutput---s3-buckets) - [Logging to DynamoDB](#logging-proxy-inputoutput---dynamodb) @@ -297,6 +298,106 @@ ModelResponse( ``` +## Custom Callback APIs [Async] + +:::info + +This is an Enterprise only feature [Get Started with Enterprise here](https://github.com/BerriAI/litellm/tree/main/enterprise) + +::: + +Use this if you: +- Want to use custom callbacks written in a non Python programming language +- Want your callbacks to run on a different microservice + +#### Step 1. Create your generic logging API endpoint +Set up a generic API endpoint that can receive data in JSON format. The data will be included within a "data" field. + +Your server should support the following Request format: + +```shell +curl --location https://your-domain.com/log-event \ + --request POST \ + --header "Content-Type: application/json" \ + --data '{ + "data": { + "id": "chatcmpl-8sgE89cEQ4q9biRtxMvDfQU1O82PT", + "call_type": "acompletion", + "cache_hit": "None", + "startTime": "2024-02-15 16:18:44.336280", + "endTime": "2024-02-15 16:18:45.045539", + "model": "gpt-3.5-turbo", + "user": "ishaan-2", + "modelParameters": "{'temperature': 0.7, 'max_tokens': 10, 'user': 'ishaan-2', 'extra_body': {}}", + "messages": "[{'role': 'user', 'content': 'This is a test'}]", + "response": "ModelResponse(id='chatcmpl-8sgE89cEQ4q9biRtxMvDfQU1O82PT', choices=[Choices(finish_reason='length', index=0, message=Message(content='Great! How can I assist you with this test', role='assistant'))], created=1708042724, model='gpt-3.5-turbo-0613', object='chat.completion', system_fingerprint=None, usage=Usage(completion_tokens=10, prompt_tokens=11, total_tokens=21))", + "usage": "Usage(completion_tokens=10, prompt_tokens=11, total_tokens=21)", + "metadata": "{}", + "cost": "3.65e-05" + } + }' +``` + +Reference FastAPI Python Server + +Here's a reference FastAPI Server that is compatible with LiteLLM Proxy: + +```python +# this is an example endpoint to receive data from litellm +from fastapi import FastAPI, HTTPException, Request + +app = FastAPI() + + +@app.post("/log-event") +async def log_event(request: Request): + try: + print("Received /log-event request") + # Assuming the incoming request has JSON data + data = await request.json() + print("Received request data:") + print(data) + + # Your additional logic can go here + # For now, just printing the received data + + return {"message": "Request received successfully"} + except Exception as e: + print(f"Error processing request: {str(e)}") + import traceback + + traceback.print_exc() + raise HTTPException(status_code=500, detail="Internal Server Error") + + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="127.0.0.1", port=8000) + + +``` + + +#### Step 2. Set your `GENERIC_LOGGER_ENDPOINT` to the endpoint + route we should send callback logs to + +```shell +os.environ["GENERIC_LOGGER_ENDPOINT"] = "http://localhost:8000/log-event" +``` + +#### Step 3. Create a `config.yaml` file and set `litellm_settings`: `success_callback` = ["generic"] + +Example litellm proxy config.yaml +```yaml +model_list: + - model_name: gpt-3.5-turbo + litellm_params: + model: gpt-3.5-turbo +litellm_settings: + success_callback: ["generic"] +``` + +Start the LiteLLM Proxy and make a test request to verify the logs reached your callback API + ## Logging Proxy Input/Output - Langfuse We will use the `--config` to set `litellm.success_callback = ["langfuse"]` this will log all successfull LLM calls to langfuse diff --git a/enterprise/README.md b/enterprise/README.md index 0818e9a58..fd7e68fd2 100644 --- a/enterprise/README.md +++ b/enterprise/README.md @@ -1,11 +1,12 @@ ## LiteLLM Enterprise -Code in this folder is licensed under a commercial license. Please review the [LICENSE](/LICENSE.md) file within the /enterprise folder +Code in this folder is licensed under a commercial license. Please review the [LICENSE](./LICENSE.md) file within the /enterprise folder **These features are covered under the LiteLLM Enterprise contract** 👉 **Using in an Enterprise / Need specific features ?** Meet with us [here](https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat?month=2024-02) ## Features: -- Custom API / microservice callbacks +- Custom API / microservice callbacks +- Google Text Moderation API diff --git a/enterprise/callbacks/example_logging_api.py b/enterprise/callbacks/example_logging_api.py new file mode 100644 index 000000000..57ea99a67 --- /dev/null +++ b/enterprise/callbacks/example_logging_api.py @@ -0,0 +1,31 @@ +# this is an example endpoint to receive data from litellm +from fastapi import FastAPI, HTTPException, Request + +app = FastAPI() + + +@app.post("/log-event") +async def log_event(request: Request): + try: + print("Received /log-event request") + # Assuming the incoming request has JSON data + data = await request.json() + print("Received request data:") + print(data) + + # Your additional logic can go here + # For now, just printing the received data + + return {"message": "Request received successfully"} + except Exception as e: + print(f"Error processing request: {str(e)}") + import traceback + + traceback.print_exc() + raise HTTPException(status_code=500, detail="Internal Server Error") + + +if __name__ == "__main__": + import uvicorn + + uvicorn.run(app, host="127.0.0.1", port=8000) diff --git a/enterprise/callbacks/generic_api_callback.py b/enterprise/callbacks/generic_api_callback.py new file mode 100644 index 000000000..076c13d5e --- /dev/null +++ b/enterprise/callbacks/generic_api_callback.py @@ -0,0 +1,128 @@ +# callback to make a request to an API endpoint + +#### What this does #### +# On success, logs events to Promptlayer +import dotenv, os +import requests + +from litellm.proxy._types import UserAPIKeyAuth +from litellm.caching import DualCache + +from typing import Literal, Union + +dotenv.load_dotenv() # Loading env variables using dotenv +import traceback + + +#### What this does #### +# On success + failure, log events to Supabase + +import dotenv, os +import requests + +dotenv.load_dotenv() # Loading env variables using dotenv +import traceback +import datetime, subprocess, sys +import litellm, uuid +from litellm._logging import print_verbose, verbose_logger + + +class GenericAPILogger: + # Class variables or attributes + def __init__(self, endpoint=None, headers=None): + try: + if endpoint == None: + # check env for "GENERIC_LOGGER_ENDPOINT" + if os.getenv("GENERIC_LOGGER_ENDPOINT"): + # Do something with the endpoint + endpoint = os.getenv("GENERIC_LOGGER_ENDPOINT") + else: + # Handle the case when the endpoint is not found in the environment variables + raise ValueError( + f"endpoint not set for GenericAPILogger, GENERIC_LOGGER_ENDPOINT not found in environment variables" + ) + headers = headers or litellm.generic_logger_headers + self.endpoint = endpoint + self.headers = headers + + verbose_logger.debug( + f"in init GenericAPILogger, endpoint {self.endpoint}, headers {self.headers}" + ) + + pass + + except Exception as e: + print_verbose(f"Got exception on init GenericAPILogger client {str(e)}") + raise e + + # This is sync, because we run this in a separate thread. Running in a sepearate thread ensures it will never block an LLM API call + # Experience with s3, Langfuse shows that async logging events are complicated and can block LLM calls + def log_event( + self, kwargs, response_obj, start_time, end_time, user_id, print_verbose + ): + try: + verbose_logger.debug( + f"GenericAPILogger Logging - Enters logging function for model {kwargs}" + ) + + # construct payload to send custom logger + # follows the same params as langfuse.py + litellm_params = kwargs.get("litellm_params", {}) + metadata = ( + litellm_params.get("metadata", {}) or {} + ) # if litellm_params['metadata'] == None + messages = kwargs.get("messages") + cost = kwargs.get("response_cost", 0.0) + optional_params = kwargs.get("optional_params", {}) + call_type = kwargs.get("call_type", "litellm.completion") + cache_hit = kwargs.get("cache_hit", False) + usage = response_obj["usage"] + id = response_obj.get("id", str(uuid.uuid4())) + + # Build the initial payload + payload = { + "id": id, + "call_type": call_type, + "cache_hit": cache_hit, + "startTime": start_time, + "endTime": end_time, + "model": kwargs.get("model", ""), + "user": kwargs.get("user", ""), + "modelParameters": optional_params, + "messages": messages, + "response": response_obj, + "usage": usage, + "metadata": metadata, + "cost": cost, + } + + # Ensure everything in the payload is converted to str + for key, value in payload.items(): + try: + payload[key] = str(value) + except: + # non blocking if it can't cast to a str + pass + + import json + + data = { + "data": payload, + } + data = json.dumps(data) + print_verbose(f"\nGeneric Logger - Logging payload = {data}") + + # make request to endpoint with payload + response = requests.post(self.endpoint, json=data, headers=self.headers) + + response_status = response.status_code + response_text = response.text + + print_verbose( + f"Generic Logger - final response status = {response_status}, response text = {response_text}" + ) + return response + except Exception as e: + traceback.print_exc() + verbose_logger.debug(f"Generic - {str(e)}\n{traceback.format_exc()}") + pass diff --git a/enterprise/hooks/google_text_moderation.py b/enterprise/hooks/google_text_moderation.py new file mode 100644 index 000000000..b79a32805 --- /dev/null +++ b/enterprise/hooks/google_text_moderation.py @@ -0,0 +1,53 @@ +# +-----------------------------------------------+ +# +# Google Text Moderation +# https://cloud.google.com/natural-language/docs/moderating-text +# +# +-----------------------------------------------+ +# Thank you users! We ❤️ you! - Krrish & Ishaan + + +from typing import Optional, Literal, Union +import litellm, traceback, sys, uuid +from litellm.caching import DualCache +from litellm.proxy._types import UserAPIKeyAuth +from litellm.integrations.custom_logger import CustomLogger +from fastapi import HTTPException +from litellm._logging import verbose_proxy_logger +from litellm.utils import ( + ModelResponse, + EmbeddingResponse, + ImageResponse, + StreamingChoices, +) +from datetime import datetime +import aiohttp, asyncio + + +class _ENTERPRISE_GoogleTextModeration(CustomLogger): + user_api_key_cache = None + + # Class variables or attributes + def __init__(self, mock_testing: bool = False): + pass + + def print_verbose(self, print_statement): + try: + verbose_proxy_logger.debug(print_statement) + if litellm.set_verbose: + print(print_statement) # noqa + except: + pass + + async def async_pre_call_hook( + self, + user_api_key_dict: UserAPIKeyAuth, + cache: DualCache, + data: dict, + call_type: str, + ): + """ + - Calls Google's Text Moderation API + - Rejects request if it fails safety check + """ + pass diff --git a/litellm/__init__.py b/litellm/__init__.py index 00d7488c9..a7f232f76 100644 --- a/litellm/__init__.py +++ b/litellm/__init__.py @@ -146,6 +146,7 @@ model_cost_map_url: str = "https://raw.githubusercontent.com/BerriAI/litellm/mai suppress_debug_info = False dynamodb_table_name: Optional[str] = None s3_callback_params: Optional[Dict] = None +generic_logger_headers: Optional[Dict] = None default_key_generate_params: Optional[Dict] = None upperbound_key_generate_params: Optional[Dict] = None default_team_settings: Optional[List] = None diff --git a/litellm/_redis.py b/litellm/_redis.py index 4484926d4..69ff6f3f2 100644 --- a/litellm/_redis.py +++ b/litellm/_redis.py @@ -98,6 +98,9 @@ def _get_redis_client_logic(**env_overrides): def get_redis_client(**env_overrides): redis_kwargs = _get_redis_client_logic(**env_overrides) if "url" in redis_kwargs and redis_kwargs["url"] is not None: + redis_kwargs.pop( + "connection_pool", None + ) # redis.from_url doesn't support setting your own connection pool return redis.Redis.from_url(**redis_kwargs) return redis.Redis(**redis_kwargs) @@ -105,6 +108,9 @@ def get_redis_client(**env_overrides): def get_redis_async_client(**env_overrides): redis_kwargs = _get_redis_client_logic(**env_overrides) if "url" in redis_kwargs and redis_kwargs["url"] is not None: + redis_kwargs.pop( + "connection_pool", None + ) # redis.from_url doesn't support setting your own connection pool return async_redis.Redis.from_url(**redis_kwargs) return async_redis.Redis( socket_timeout=5, diff --git a/litellm/caching.py b/litellm/caching.py index 564972068..567b9aadb 100644 --- a/litellm/caching.py +++ b/litellm/caching.py @@ -124,7 +124,7 @@ class RedisCache(BaseCache): self.redis_client.set(name=key, value=str(value), ex=ttl) except Exception as e: # NON blocking - notify users Redis is throwing an exception - logging.debug("LiteLLM Caching: set() - Got exception from REDIS : ", e) + print_verbose("LiteLLM Caching: set() - Got exception from REDIS : ", e) async def async_set_cache(self, key, value, **kwargs): _redis_client = self.init_async_client() @@ -134,10 +134,12 @@ class RedisCache(BaseCache): f"Set ASYNC Redis Cache: key: {key}\nValue {value}\nttl={ttl}" ) try: - await redis_client.set(name=key, value=json.dumps(value), ex=ttl) + await redis_client.set( + name=key, value=json.dumps(value), ex=ttl, get=True + ) except Exception as e: # NON blocking - notify users Redis is throwing an exception - logging.debug("LiteLLM Caching: set() - Got exception from REDIS : ", e) + print_verbose("LiteLLM Caching: set() - Got exception from REDIS : ", e) async def async_set_cache_pipeline(self, cache_list, ttl=None): """ diff --git a/litellm/integrations/langfuse.py b/litellm/integrations/langfuse.py index b548f22bc..7ce843339 100644 --- a/litellm/integrations/langfuse.py +++ b/litellm/integrations/langfuse.py @@ -259,6 +259,7 @@ class LangFuseLogger: if key in [ "user_api_key", "user_api_key_user_id", + "user_api_key_team_id", "semantic-similarity", ]: tags.append(f"{key}:{value}") diff --git a/litellm/llms/vertex_ai.py b/litellm/llms/vertex_ai.py index 816ded394..2e5fb3dd3 100644 --- a/litellm/llms/vertex_ai.py +++ b/litellm/llms/vertex_ai.py @@ -343,24 +343,31 @@ def completion( llm_model = CodeChatModel.from_pretrained(model) mode = "chat" request_str += f"llm_model = CodeChatModel.from_pretrained({model})\n" - else: # assume vertex model garden - client = aiplatform.gapic.PredictionServiceClient( - client_options=client_options + elif model == "private": + mode = "private" + model = optional_params.pop("model_id", None) + # private endpoint requires a dict instead of JSON + instances = [optional_params.copy()] + instances[0]["prompt"] = prompt + llm_model = aiplatform.PrivateEndpoint( + endpoint_name=model, + project=vertex_project, + location=vertex_location, ) + request_str += f"llm_model = aiplatform.PrivateEndpoint(endpoint_name={model}, project={vertex_project}, location={vertex_location})\n" + else: # assume vertex model garden on public endpoint + mode = "custom" - instances = [optional_params] + instances = [optional_params.copy()] instances[0]["prompt"] = prompt instances = [ json_format.ParseDict(instance_dict, Value()) for instance_dict in instances ] - llm_model = client.endpoint_path( - project=vertex_project, location=vertex_location, endpoint=model - ) - - mode = "custom" - request_str += f"llm_model = client.endpoint_path(project={vertex_project}, location={vertex_location}, endpoint={model})\n" + # Will determine the API used based on async parameter + llm_model = None + # NOTE: async prediction and streaming under "private" mode isn't supported by aiplatform right now if acompletion == True: data = { "llm_model": llm_model, @@ -532,9 +539,6 @@ def completion( """ Vertex AI Model Garden """ - request_str += ( - f"client.predict(endpoint={llm_model}, instances={instances})\n" - ) ## LOGGING logging_obj.pre_call( input=prompt, @@ -544,11 +548,21 @@ def completion( "request_str": request_str, }, ) - - response = client.predict( - endpoint=llm_model, - instances=instances, + llm_model = aiplatform.gapic.PredictionServiceClient( + client_options=client_options + ) + request_str += f"llm_model = aiplatform.gapic.PredictionServiceClient(client_options={client_options})\n" + endpoint_path = llm_model.endpoint_path( + project=vertex_project, location=vertex_location, endpoint=model + ) + request_str += ( + f"llm_model.predict(endpoint={endpoint_path}, instances={instances})\n" + ) + response = llm_model.predict( + endpoint=endpoint_path, + instances=instances ).predictions + completion_response = response[0] if ( isinstance(completion_response, str) @@ -558,6 +572,36 @@ def completion( if "stream" in optional_params and optional_params["stream"] == True: response = TextStreamer(completion_response) return response + elif mode == "private": + """ + Vertex AI Model Garden deployed on private endpoint + """ + ## LOGGING + logging_obj.pre_call( + input=prompt, + api_key=None, + additional_args={ + "complete_input_dict": optional_params, + "request_str": request_str, + }, + ) + request_str += ( + f"llm_model.predict(instances={instances})\n" + ) + response = llm_model.predict( + instances=instances + ).predictions + + completion_response = response[0] + if ( + isinstance(completion_response, str) + and "\nOutput:\n" in completion_response + ): + completion_response = completion_response.split("\nOutput:\n", 1)[1] + if "stream" in optional_params and optional_params["stream"] == True: + response = TextStreamer(completion_response) + return response + ## LOGGING logging_obj.post_call( input=prompt, api_key=None, original_response=completion_response @@ -722,17 +766,6 @@ async def async_completion( Vertex AI Model Garden """ from google.cloud import aiplatform - - async_client = aiplatform.gapic.PredictionServiceAsyncClient( - client_options=client_options - ) - llm_model = async_client.endpoint_path( - project=vertex_project, location=vertex_location, endpoint=model - ) - - request_str += ( - f"client.predict(endpoint={llm_model}, instances={instances})\n" - ) ## LOGGING logging_obj.pre_call( input=prompt, @@ -743,8 +776,18 @@ async def async_completion( }, ) - response_obj = await async_client.predict( - endpoint=llm_model, + llm_model = aiplatform.gapic.PredictionServiceAsyncClient( + client_options=client_options + ) + request_str += f"llm_model = aiplatform.gapic.PredictionServiceAsyncClient(client_options={client_options})\n" + endpoint_path = llm_model.endpoint_path( + project=vertex_project, location=vertex_location, endpoint=model + ) + request_str += ( + f"llm_model.predict(endpoint={endpoint_path}, instances={instances})\n" + ) + response_obj = await llm_model.predict( + endpoint=endpoint_path, instances=instances, ) response = response_obj.predictions @@ -754,6 +797,23 @@ async def async_completion( and "\nOutput:\n" in completion_response ): completion_response = completion_response.split("\nOutput:\n", 1)[1] + + elif mode == "private": + request_str += ( + f"llm_model.predict_async(instances={instances})\n" + ) + response_obj = await llm_model.predict_async( + instances=instances, + ) + + response = response_obj.predictions + completion_response = response[0] + if ( + isinstance(completion_response, str) + and "\nOutput:\n" in completion_response + ): + completion_response = completion_response.split("\nOutput:\n", 1)[1] + ## LOGGING logging_obj.post_call( input=prompt, api_key=None, original_response=completion_response @@ -894,15 +954,8 @@ async def async_streaming( response = llm_model.predict_streaming_async(prompt, **optional_params) elif mode == "custom": from google.cloud import aiplatform + stream = optional_params.pop("stream", None) - async_client = aiplatform.gapic.PredictionServiceAsyncClient( - client_options=client_options - ) - llm_model = async_client.endpoint_path( - project=vertex_project, location=vertex_location, endpoint=model - ) - - request_str += f"client.predict(endpoint={llm_model}, instances={instances})\n" ## LOGGING logging_obj.pre_call( input=prompt, @@ -912,9 +965,34 @@ async def async_streaming( "request_str": request_str, }, ) + llm_model = aiplatform.gapic.PredictionServiceAsyncClient( + client_options=client_options + ) + request_str += f"llm_model = aiplatform.gapic.PredictionServiceAsyncClient(client_options={client_options})\n" + endpoint_path = llm_model.endpoint_path( + project=vertex_project, location=vertex_location, endpoint=model + ) + request_str += f"client.predict(endpoint={endpoint_path}, instances={instances})\n" + response_obj = await llm_model.predict( + endpoint=endpoint_path, + instances=instances, + ) - response_obj = await async_client.predict( - endpoint=llm_model, + response = response_obj.predictions + completion_response = response[0] + if ( + isinstance(completion_response, str) + and "\nOutput:\n" in completion_response + ): + completion_response = completion_response.split("\nOutput:\n", 1)[1] + if stream: + response = TextStreamer(completion_response) + + elif mode == "private": + stream = optional_params.pop("stream", None) + _ = instances[0].pop("stream", None) + request_str += f"llm_model.predict_async(instances={instances})\n" + response_obj = await llm_model.predict_async( instances=instances, ) response = response_obj.predictions @@ -924,8 +1002,9 @@ async def async_streaming( and "\nOutput:\n" in completion_response ): completion_response = completion_response.split("\nOutput:\n", 1)[1] - if "stream" in optional_params and optional_params["stream"] == True: + if stream: response = TextStreamer(completion_response) + streamwrapper = CustomStreamWrapper( completion_stream=response, model=model, diff --git a/litellm/main.py b/litellm/main.py index 53567ee7e..93ea3c644 100644 --- a/litellm/main.py +++ b/litellm/main.py @@ -10,6 +10,7 @@ import os, openai, sys, json, inspect, uuid, datetime, threading from typing import Any, Literal, Union from functools import partial + import dotenv, traceback, random, asyncio, time, contextvars from copy import deepcopy import httpx diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 7a7f154e3..fa50b06f1 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -642,21 +642,40 @@ "mode": "chat" }, "gemini-pro": { - "max_tokens": 30720, + "max_tokens": 32760, "max_output_tokens": 2048, "input_cost_per_token": 0.00000025, "output_cost_per_token": 0.0000005, "litellm_provider": "vertex_ai-language-models", "mode": "chat" }, + "gemini-1.0-pro": { + "max_tokens": 32760, + "max_output_tokens": 8192, + "input_cost_per_token": 0.00000025, + "output_cost_per_token": 0.0000005, + "litellm_provider": "vertex_ai-language-models", + "mode": "chat" + }, "gemini-pro-vision": { - "max_tokens": 30720, + "max_tokens": 16384, "max_output_tokens": 2048, "input_cost_per_token": 0.00000025, "output_cost_per_token": 0.0000005, "litellm_provider": "vertex_ai-vision-models", "mode": "chat" }, + "gemini-1.0-pro-vision": { + "max_tokens": 16384, + "max_output_tokens": 2048, + "max_images_per_prompt": 16, + "max_videos_per_prompt": 1, + "max_video_length": 2, + "input_cost_per_token": 0.00000025, + "output_cost_per_token": 0.0000005, + "litellm_provider": "vertex_ai-vision-models", + "mode": "chat" + }, "textembedding-gecko": { "max_tokens": 3072, "max_input_tokens": 3072, diff --git a/litellm/proxy/_experimental/out/404.html b/litellm/proxy/_experimental/out/404.html index 68e7eafd9..03563194a 100644 --- a/litellm/proxy/_experimental/out/404.html +++ b/litellm/proxy/_experimental/out/404.html @@ -1 +1 @@ -404: This page could not be found.🚅 LiteLLM

404

This page could not be found.

\ No newline at end of file +404: This page could not be found.🚅 LiteLLM

404

This page could not be found.

\ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/app/page-fcb69349f15d154b.js b/litellm/proxy/_experimental/out/_next/static/chunks/app/page-7bb820bd6902dbf2.js similarity index 62% rename from litellm/proxy/_experimental/out/_next/static/chunks/app/page-fcb69349f15d154b.js rename to litellm/proxy/_experimental/out/_next/static/chunks/app/page-7bb820bd6902dbf2.js index ae2f60d88..5402c8d1f 100644 --- a/litellm/proxy/_experimental/out/_next/static/chunks/app/page-fcb69349f15d154b.js +++ b/litellm/proxy/_experimental/out/_next/static/chunks/app/page-7bb820bd6902dbf2.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{20661:function(e,t,n){Promise.resolve().then(n.bind(n,48016))},48016:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return ec}});var s=n(3827),l=n(64090),r=n(47907),a=n(8792),o=n(2179),i=e=>{let{userID:t,userRole:n,userEmail:l}=e;return console.log("User ID:",t),console.log("userEmail:",l),(0,s.jsxs)("nav",{className:"left-0 right-0 top-0 flex justify-between items-center h-12 mb-4",children:[(0,s.jsx)("div",{className:"text-left mx-4 my-2 absolute top-0 left-0",children:(0,s.jsx)("div",{className:"flex flex-col items-center",children:(0,s.jsx)(a.default,{href:"/",children:(0,s.jsx)("button",{className:"text-gray-800 text-2xl px-4 py-1 rounded text-center",children:"\uD83D\uDE85 LiteLLM"})})})}),(0,s.jsx)("div",{className:"text-right mx-4 my-2 absolute top-0 right-0",children:(0,s.jsxs)(o.Z,{variant:"secondary",children:[l,(0,s.jsxs)("p",{children:["Role: ",n]}),(0,s.jsxs)("p",{children:["ID: ",t]})]})})]})},c=n(80588);let d=async(e,t,n)=>{try{if(console.log("Form Values in keyCreateCall:",n),n.description&&(n.metadata||(n.metadata={}),n.metadata.description=n.description,delete n.description,n.metadata=JSON.stringify(n.metadata)),n.metadata){console.log("formValues.metadata:",n.metadata);try{n.metadata=JSON.parse(n.metadata)}catch(e){throw c.ZP.error("Failed to parse metadata: "+e),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",n);let s=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:t,...n})});if(!s.ok){let e=await s.text();throw c.ZP.error("Failed to create key: "+e),console.error("Error response from the server:",e),Error("Network response was not ok")}let l=await s.json();return console.log("API Response:",l),l}catch(e){throw console.error("Failed to create key:",e),e}},m=async(e,t)=>{try{console.log("in keyDeleteCall:",t),c.ZP.info("Making key delete request");let n=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[t]})});if(!n.ok){let e=await n.text();throw c.ZP.error("Failed to delete key: "+e),Error("Network response was not ok")}let s=await n.json();return console.log(s),c.ZP.success("API Key Deleted"),s}catch(e){throw console.error("Failed to create key:",e),e}},h=async(e,t,n)=>{try{let s="/user/info";"App Owner"==n&&(s="".concat(s,"/?user_id=").concat(t)),c.ZP.info("Requesting user data");let l=await fetch(s,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw c.ZP.error(e),Error("Network response was not ok")}let r=await l.json();return c.ZP.info("Received user data"),r}catch(e){throw console.error("Failed to create key:",e),e}},u=async(e,t,n)=>{try{c.ZP.info("Requesting model data");let t=await fetch("/model/info",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw c.ZP.error(e),Error("Network response was not ok")}let n=await t.json();return c.ZP.info("Received model data"),n}catch(e){throw console.error("Failed to create key:",e),e}},x=async(e,t)=>{try{let n="/spend/logs";console.log("in keySpendLogsCall:",n);let s=await fetch("".concat(n,"/?api_key=").concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw c.ZP.error(e),Error("Network response was not ok")}let l=await s.json();return console.log(l),l}catch(e){throw console.error("Failed to create key:",e),e}},p=async(e,t,n,s,l,r)=>{try{let t="/spend/logs";t="App Owner"==n?"".concat(t,"/?user_id=").concat(s,"&start_date=").concat(l,"&end_date=").concat(r):"".concat(t,"/?start_date=").concat(l,"&end_date=").concat(r),c.ZP.info("Making spend logs request");let a=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!a.ok){let e=await a.text();throw c.ZP.error(e),Error("Network response was not ok")}let o=await a.json();return console.log(o),c.ZP.success("Spend Logs received"),o}catch(e){throw console.error("Failed to create key:",e),e}},j=async(e,t)=>{try{let n=await fetch("/key/info",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:t})});if(!n.ok){let e=await n.text();throw c.ZP.error(e),Error("Network response was not ok")}let s=await n.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},g=async(e,t)=>{try{let n="/spend/users";console.log("in spendUsersCall:",n);let s=await fetch("".concat(n,"/?user_id=").concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw c.ZP.error(e),Error("Network response was not ok")}let l=await s.json();return console.log(l),l}catch(e){throw console.error("Failed to get spend for user",e),e}};var y=n(10384),f=n(46453),Z=n(71801),w=n(13969),k=n(12143),_=n(77171),v=n(29714),b=n(88707),S=n(1861);let{Option:N}=w.default;var I=e=>{let{userID:t,userRole:n,accessToken:r,data:a,userModels:i,setData:m}=e,[h]=k.Z.useForm(),[u,x]=(0,l.useState)(!1),[p,j]=(0,l.useState)(null),g=()=>{x(!1),h.resetFields()},I=()=>{x(!1),j(null),h.resetFields()},A=async e=>{try{c.ZP.info("Making API Call"),x(!0);let n=await d(r,t,e);m(e=>e?[...e,n]:[n]),j(n.key),c.ZP.success("API Key Created"),h.resetFields(),localStorage.removeItem("userData"+t)}catch(e){console.error("Error creating the key:",e)}};return(0,s.jsxs)("div",{children:[(0,s.jsx)(o.Z,{className:"mx-auto",onClick:()=>x(!0),children:"+ Create New Key"}),(0,s.jsx)(_.Z,{title:"Create Key",visible:u,width:800,footer:null,onOk:g,onCancel:I,children:(0,s.jsxs)(k.Z,{form:h,onFinish:A,labelCol:{span:6},wrapperCol:{span:16},labelAlign:"left",children:["App Owner"===n||"Admin"===n?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(k.Z.Item,{label:"Key Name",name:"key_alias",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Team ID",name:"team_id",children:(0,s.jsx)(v.Z,{placeholder:"ai_team"})}),(0,s.jsx)(k.Z.Item,{label:"Models",name:"models",children:(0,s.jsx)(w.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:i.map(e=>(0,s.jsx)(N,{value:e,children:e},e))})}),(0,s.jsx)(k.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,s.jsx)(b.Z,{step:.01,precision:2,width:200})}),(0,s.jsx)(k.Z.Item,{label:"Duration (eg: 30s, 30h, 30d)",name:"duration",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Metadata",name:"metadata",children:(0,s.jsx)(v.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(k.Z.Item,{label:"Key Name",name:"key_alias",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Team ID (Contact Group)",name:"team_id",children:(0,s.jsx)(v.Z,{placeholder:"ai_team"})}),(0,s.jsx)(k.Z.Item,{label:"Description",name:"description",children:(0,s.jsx)(v.Z.TextArea,{placeholder:"Enter description",rows:4})})]}),(0,s.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,s.jsx)(S.ZP,{htmlType:"submit",children:"Create Key"})})]})}),p&&(0,s.jsx)(_.Z,{title:"Save your key",visible:u,onOk:g,onCancel:I,footer:null,children:(0,s.jsxs)(f.Z,{numItems:1,className:"gap-2 w-full",children:[(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons, ",(0,s.jsx)("b",{children:"you will not be able to view it again"})," ","through your LiteLLM account. If you lose this secret key, you will need to generate a new one."]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:null!=p?(0,s.jsxs)(Z.Z,{children:["API Key: ",p]}):(0,s.jsx)(Z.Z,{children:"Key being created, this might take 30s"})})]})})]})},A=n(33393),C=n(13810),D=n(61244),T=n(10827),P=n(3851),E=n(2044),O=n(64167),R=n(74480),M=n(7178),U=n(42440),F=n(9853),K=n(67989),L=n(56863),z=e=>{let{token:t,accessToken:n,keySpend:r,keyBudget:a,keyName:i}=e,[c,d]=(0,l.useState)(!1),[m,h]=(0,l.useState)(null),[u,p]=(0,l.useState)(null),j=async()=>{try{if(null==n||null==t)return;console.log("accessToken: ".concat(n,"; token: ").concat(t));let e=await x(n,t);console.log("Response:",e);let s=Object.values(e).reduce((e,t)=>{let n=new Date(t.startTime),s=new Intl.DateTimeFormat("en-US",{day:"2-digit",month:"short"}).format(n);return e[s]=(e[s]||0)+t.spend,e},{}),l=Object.entries(s);l.sort((e,t)=>{let[n]=e,[s]=t,l=new Date(n),r=new Date(s);return l.getTime()-r.getTime()});let r=Object.fromEntries(l);console.log(r);let a=Object.values(e).reduce((e,t)=>{let n=t.user;return e[n]=(e[n]||0)+t.spend,e},{});console.log(s),console.log(a);let o=[];for(let[e,t]of Object.entries(r))o.push({day:e,spend:t});let i=Object.entries(a).sort((e,t)=>t[1]-e[1]).slice(0,5).map(e=>{let[t,n]=e;return{name:t,value:n}});h(o),p(i),console.log("arrayBarChart:",o)}catch(e){console.error("There was an error fetching the data",e)}};return t?(0,s.jsxs)("div",{children:[(0,s.jsx)(o.Z,{className:"mx-auto",onClick:()=>{console.log("Show Modal triggered"),d(!0),j()},children:"View Spend Report"}),(0,s.jsxs)(_.Z,{visible:c,width:1e3,onOk:()=>{d(!1)},onCancel:()=>{d(!1)},footer:null,children:[(0,s.jsxs)(U.Z,{style:{textAlign:"left"},children:["Key Name: ",i]}),(0,s.jsxs)(L.Z,{children:["Monthly Spend $",r]}),(0,s.jsx)(C.Z,{className:"mt-6 mb-6",children:m&&(0,s.jsx)(F.Z,{className:"mt-6",data:m,colors:["green"],index:"day",categories:["spend"],yAxisWidth:48})}),(0,s.jsx)(U.Z,{className:"mt-6",children:"Top 5 Users Spend (USD)"}),(0,s.jsx)(C.Z,{className:"mb-6",children:u&&(0,s.jsx)(K.Z,{className:"mt-6",data:u,color:"teal"})})]})]}):null},B=e=>{let{userID:t,accessToken:n,data:r,setData:a}=e,[i,c]=(0,l.useState)(!1),[d,h]=(0,l.useState)(!1),[u,x]=(0,l.useState)(null),p=async e=>{null!=r&&(x(e),localStorage.removeItem("userData"+t),h(!0))},j=async()=>{if(null!=u&&null!=r){try{await m(n,u);let e=r.filter(e=>e.token!==u);a(e)}catch(e){console.error("Error deleting the key:",e)}h(!1),x(null)}};if(null!=r)return console.log("RERENDER TRIGGERED"),(0,s.jsxs)(C.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4",children:[(0,s.jsx)(U.Z,{children:"API Keys"}),(0,s.jsxs)(T.Z,{className:"mt-5",children:[(0,s.jsx)(O.Z,{children:(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(R.Z,{children:"Key Alias"}),(0,s.jsx)(R.Z,{children:"Secret Key"}),(0,s.jsx)(R.Z,{children:"Spend (USD)"}),(0,s.jsx)(R.Z,{children:"Key Budget (USD)"}),(0,s.jsx)(R.Z,{children:"Team ID"}),(0,s.jsx)(R.Z,{children:"Metadata"}),(0,s.jsx)(R.Z,{children:"Models"}),(0,s.jsx)(R.Z,{children:"TPM / RPM Limits"}),(0,s.jsx)(R.Z,{children:"Expires"})]})}),(0,s.jsx)(P.Z,{children:r.map(e=>(console.log(e),"litellm-dashboard"===e.team_id)?null:(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(E.Z,{children:null!=e.key_alias?(0,s.jsx)(Z.Z,{children:e.key_alias}):(0,s.jsx)(Z.Z,{children:"Not Set"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.key_name})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.spend})}),(0,s.jsx)(E.Z,{children:null!=e.max_budget?(0,s.jsx)(Z.Z,{children:e.max_budget}):(0,s.jsx)(Z.Z,{children:"Unlimited Budget"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.team_id})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:JSON.stringify(e.metadata)})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:JSON.stringify(e.models)})}),(0,s.jsx)(E.Z,{children:(0,s.jsxs)(Z.Z,{children:["TPM Limit: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,s.jsx)("br",{})," RPM Limit:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,s.jsx)(E.Z,{children:null!=e.expires?(0,s.jsx)(Z.Z,{children:e.expires}):(0,s.jsx)(Z.Z,{children:"Never expires"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(D.Z,{onClick:()=>p(e.token),icon:A.Z,size:"sm"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(z,{token:e.token,accessToken:n,keySpend:e.spend,keyBudget:e.max_budget,keyName:e.key_name})})]},e.token))})]}),d&&(0,s.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,s.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,s.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,s.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,s.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,s.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,s.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,s.jsx)("div",{className:"sm:flex sm:items-start",children:(0,s.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,s.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Key"}),(0,s.jsx)("div",{className:"mt-2",children:(0,s.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this key ?"})})]})})}),(0,s.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,s.jsx)(o.Z,{onClick:j,color:"red",className:"ml-2",children:"Delete"}),(0,s.jsx)(o.Z,{onClick:()=>{h(!1),x(null)},children:"Cancel"})]})]})]})})]})},J=e=>{let{userID:t,userSpendData:n,userRole:r,accessToken:a}=e;console.log("User SpendData:",n);let[o,i]=(0,l.useState)(null==n?void 0:n.spend),[c,d]=(0,l.useState)((null==n?void 0:n.max_budget)||null);return(0,l.useEffect)(()=>{(async()=>{if("Admin"===r)try{let e=await g(a,"litellm-proxy-budget");console.log("Result from callSpendUsers:",e);let t=e[0];i(null==t?void 0:t.spend),d((null==t?void 0:t.max_budget)||null)}catch(e){console.error("Failed to get spend for user",e)}})()},[r,a,t]),(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)(C.Z,{className:"mx-auto mb-4",children:[(0,s.jsxs)(L.Z,{children:["$",o]}),(0,s.jsxs)(U.Z,{children:["/ ",null!==c?"$".concat(c," limit"):"No limit"]})]})})},q=n(37963);console.log("isLocal:",!1);var G=e=>{let{userID:t,userRole:n,setUserRole:a,userEmail:o,setUserEmail:i}=e,[c,d]=(0,l.useState)(null),[m,x]=(0,l.useState)(null),p=(0,r.useSearchParams)();p.get("viewSpend"),(0,r.useRouter)();let j=p.get("token"),[g,Z]=(0,l.useState)(null),[w,k]=(0,l.useState)([]);if((0,l.useEffect)(()=>{if(j){let e=(0,q.o)(j);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),Z(e.key),e.user_role){let t=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":return"Admin";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",t),a(t)}else console.log("User role not defined");e.user_email?i(e.user_email):console.log("User Email is not set ".concat(e))}}if(t&&g&&n&&!c){let e=localStorage.getItem("userData"+t),s=localStorage.getItem("userSpendData"+t),l=localStorage.getItem("userModels"+t);e&&s&&l?(d(JSON.parse(e)),x(JSON.parse(s)),k(JSON.parse(l))):(async()=>{try{let e=await h(g,t,n);x(e.user_info),d(e.keys),localStorage.setItem("userData"+t,JSON.stringify(e.keys)),localStorage.setItem("userSpendData"+t,JSON.stringify(e.user_info));let s=await u(g,t,n);console.log("model_info:",s);let l=s.data.map(e=>e.model_name);console.log("available_model_names:",l),k(l),console.log("userModels:",w),localStorage.setItem("userModels"+t,JSON.stringify(l))}catch(e){console.error("There was an error fetching the data",e)}})()}},[t,j,g,c,n]),null==t||null==j){let e="/sso/key/generate";return console.log("Full URL:",e),window.location.href=e,null}return null==g?null:(null==n&&a("App Owner"),(0,s.jsx)("div",{children:(0,s.jsx)(f.Z,{numItems:1,className:"gap-0 p-10 h-[75vh] w-full",children:(0,s.jsxs)(y.Z,{numColSpan:1,children:[(0,s.jsx)(J,{userID:t,userSpendData:m,userRole:n,accessToken:g}),(0,s.jsx)(B,{userID:t,accessToken:g,data:c,setData:d}),(0,s.jsx)(I,{userID:t,userRole:n,userModels:w,accessToken:g,data:c,setData:d})]})})}))},$=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,[o,i]=(0,l.useState)({data:[]});if((0,l.useEffect)(()=>{if(!t||!n||!r||!a)return;let e=async()=>{try{let e=await u(t,a,r);console.log("Model data response:",e.data),i(e)}catch(e){console.error("There was an error fetching the model data",e)}};t&&n&&r&&a&&e()},[t,n,r,a]),!o)return(0,s.jsx)("div",{children:"Loading..."});for(let e=0;e(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(E.Z,{children:(0,s.jsx)(U.Z,{children:e.model_name})}),(0,s.jsx)(E.Z,{children:e.provider}),(0,s.jsx)(E.Z,{children:e.input_cost}),(0,s.jsx)(E.Z,{children:e.output_cost}),(0,s.jsx)(E.Z,{children:e.max_tokens})]},e.model_name))})]})})})})},V=n(92836),W=n(26734),H=n(41608),Y=n(32126),X=n(23682),Q=n(12968),ee=n(67951);async function et(e,t,n,s){let l=new Q.ZP.OpenAI({apiKey:s,baseURL:"http://0.0.0.0:4000",dangerouslyAllowBrowser:!0});for await(let s of(await l.chat.completions.create({model:n,stream:!0,messages:[{role:"user",content:e}]})))console.log(s),s.choices[0].delta.content&&t(s.choices[0].delta.content)}var en=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,[o,i]=(0,l.useState)(""),[c,d]=(0,l.useState)([]),[m,h]=(0,l.useState)(void 0),[x,p]=(0,l.useState)(null);(0,l.useEffect)(()=>{t&&n&&r&&a&&(async()=>{let e=await u(t,a,r);console.log("model_info:",e),(null==e?void 0:e.data.length)>0&&(p(e),h(e.data[0].model_name))})()},[t,a,r]);let j=(e,t)=>{d(n=>{let s=n[n.length-1];return s&&s.role===e?[...n.slice(0,n.length-1),{role:e,content:s.content+t}]:[...n,{role:e,content:t}]})},g=async()=>{if(""!==o.trim()&&t&&n&&r&&a){d(e=>[...e,{role:"user",content:o}]);try{m&&await et(o,e=>j("assistant",e),m,t)}catch(e){console.error("Error fetching model response",e),j("assistant","Error fetching model response")}i("")}};return(0,s.jsx)("div",{style:{width:"100%",position:"relative"},children:(0,s.jsx)(f.Z,{className:"gap-2 p-10 h-[75vh] w-full",children:(0,s.jsx)(C.Z,{children:(0,s.jsxs)(W.Z,{children:[(0,s.jsxs)(H.Z,{className:"mt-4",children:[(0,s.jsx)(V.Z,{children:"Chat"}),(0,s.jsx)(V.Z,{children:"API Reference"})]}),(0,s.jsxs)(X.Z,{children:[(0,s.jsxs)(Y.Z,{children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{children:"Select Model:"}),(0,s.jsx)("select",{value:m||"",onChange:e=>h(e.target.value),children:null==x?void 0:x.data.map(e=>(0,s.jsx)("option",{value:e.model_name,children:e.model_name},e.model_name))})]}),(0,s.jsxs)(T.Z,{className:"mt-5",style:{display:"block",maxHeight:"60vh",overflowY:"auto"},children:[(0,s.jsx)(O.Z,{children:(0,s.jsx)(M.Z,{children:(0,s.jsx)(E.Z,{children:(0,s.jsx)(U.Z,{children:"Chat"})})})}),(0,s.jsx)(P.Z,{children:c.map((e,t)=>(0,s.jsx)(M.Z,{children:(0,s.jsx)(E.Z,{children:"".concat(e.role,": ").concat(e.content)})},t))})]}),(0,s.jsx)("div",{className:"mt-3",style:{position:"absolute",bottom:5,width:"95%"},children:(0,s.jsxs)("div",{className:"flex",children:[(0,s.jsx)("input",{type:"text",value:o,onChange:e=>i(e.target.value),className:"flex-1 p-2 border rounded-md mr-2",placeholder:"Type your message..."}),(0,s.jsx)("button",{onClick:g,className:"p-2 bg-blue-500 text-white rounded-md",children:"Send"})]})})]}),(0,s.jsx)(Y.Z,{children:(0,s.jsxs)(W.Z,{children:[(0,s.jsxs)(H.Z,{children:[(0,s.jsx)(V.Z,{children:"OpenAI Python SDK"}),(0,s.jsx)(V.Z,{children:"LlamaIndex"}),(0,s.jsx)(V.Z,{children:"Langchain Py"})]}),(0,s.jsxs)(X.Z,{children:[(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nimport openai\nclient = openai.OpenAI(\n api_key="your_api_key",\n base_url="http://0.0.0.0:4000" # proxy base url\n)\n\nresponse = client.chat.completions.create(\n model="gpt-3.5-turbo", # model to use from Models Tab\n messages = [\n {\n "role": "user",\n "content": "this is a test request, write a short poem"\n }\n ],\n extra_body={\n "metadata": {\n "generation_name": "ishaan-generation-openai-client",\n "generation_id": "openai-client-gen-id22",\n "trace_id": "openai-client-trace-id22",\n "trace_user_id": "openai-client-user-id2"\n }\n }\n)\n\nprint(response)\n '})}),(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nimport os, dotenv\n\nfrom llama_index.llms import AzureOpenAI\nfrom llama_index.embeddings import AzureOpenAIEmbedding\nfrom llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\n\nllm = AzureOpenAI(\n engine="azure-gpt-3.5", # model_name on litellm proxy\n temperature=0.0,\n azure_endpoint="http://0.0.0.0:4000", # litellm proxy endpoint\n api_key="sk-1234", # litellm proxy API Key\n api_version="2023-07-01-preview",\n)\n\nembed_model = AzureOpenAIEmbedding(\n deployment_name="azure-embedding-model",\n azure_endpoint="http://0.0.0.0:4000",\n api_key="sk-1234",\n api_version="2023-07-01-preview",\n)\n\n\ndocuments = SimpleDirectoryReader("llama_index_data").load_data()\nservice_context = ServiceContext.from_defaults(llm=llm, embed_model=embed_model)\nindex = VectorStoreIndex.from_documents(documents, service_context=service_context)\n\nquery_engine = index.as_query_engine()\nresponse = query_engine.query("What did the author do growing up?")\nprint(response)\n\n '})}),(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.prompts.chat import (\n ChatPromptTemplate,\n HumanMessagePromptTemplate,\n SystemMessagePromptTemplate,\n)\nfrom langchain.schema import HumanMessage, SystemMessage\n\nchat = ChatOpenAI(\n openai_api_base="http://0.0.0.0:8000",\n model = "gpt-3.5-turbo",\n temperature=0.1,\n extra_body={\n "metadata": {\n "generation_name": "ishaan-generation-langchain-client",\n "generation_id": "langchain-client-gen-id22",\n "trace_id": "langchain-client-trace-id22",\n "trace_user_id": "langchain-client-user-id2"\n }\n }\n)\n\nmessages = [\n SystemMessage(\n content="You are a helpful assistant that im using to make a test request to."\n ),\n HumanMessage(\n content="test from litellm. tell me why it\'s amazing in 1 sentence"\n ),\n]\nresponse = chat(messages)\n\nprint(response)\n\n '})})]})]})})]})]})})})})},es=n(33509),el=n(30569);let{Sider:er}=es.default;var ea=e=>{let{setPage:t}=e;return(0,s.jsx)(es.default,{style:{minHeight:"100vh",maxWidth:"120px"},children:(0,s.jsx)(er,{width:120,children:(0,s.jsxs)(el.Z,{mode:"inline",defaultSelectedKeys:["1"],style:{height:"100%",borderRight:0},children:[(0,s.jsx)(el.Z.Item,{onClick:()=>t("api-keys"),children:"API Keys"},"1"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("models"),children:"Models"},"2"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("llm-playground"),children:"Chat UI"},"3"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("usage"),children:"Usage"},"4")]})})})};let eo=e=>{let{payload:t,active:n}=e;if(!n||!t)return null;let l=t[0].payload,r=l.startTime,a=Object.entries(l.models).map(e=>{let[t,n]=e;return[t,n]});a.sort((e,t)=>t[1]-e[1]);let o=a.slice(0,5);return(0,s.jsxs)("div",{className:"w-56 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown",children:[r,o.map(e=>{let[t,n]=e;return(0,s.jsx)("div",{className:"flex flex-1 space-x-10",children:(0,s.jsx)("div",{className:"p-2",children:(0,s.jsxs)("p",{className:"text-tremor-content text-xs",children:[t,":",(0,s.jsxs)("span",{className:"text-xs text-tremor-content-emphasis",children:[" ",n?n<.01?"<$0.01":n.toFixed(2):""]})]})})},t)})]})};var ei=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,o=new Date,[i,c]=(0,l.useState)([]),[d,m]=(0,l.useState)([]),[h,u]=(0,l.useState)([]),x=new Date(o.getFullYear(),o.getMonth(),1),g=new Date(o.getFullYear(),o.getMonth()+1,0),Z=k(x),w=k(g);function k(e){let t=e.getFullYear(),n=e.getMonth()+1,s=e.getDate();return"".concat(t,"-").concat(n<10?"0"+n:n,"-").concat(s<10?"0"+s:s)}return console.log("Start date is ".concat(Z)),console.log("End date is ".concat(w)),(0,l.useEffect)(()=>{t&&n&&r&&a&&(async()=>{try{await p(t,n,r,a,Z,w).then(async e=>{let n=(await j(t,function(e){let t=[];e.forEach(e=>{Object.entries(e).forEach(e=>{let[n,s]=e;"spend"!==n&&"startTime"!==n&&"models"!==n&&"users"!==n&&t.push({key:n,spend:s})})}),t.sort((e,t)=>Number(t.spend)-Number(e.spend));let n=t.slice(0,5).map(e=>e.key);return console.log("topKeys: ".concat(Object.keys(n[0]))),n}(e))).info.map(e=>({key:(e.key_name||e.key_alias||e.token).substring(0,7),spend:e.spend}));m(n),u(function(e){let t={};e.forEach(e=>{Object.entries(e.users).forEach(e=>{let[n,s]=e;""!==n&&null!=n&&"None"!=n&&(t[n]||(t[n]=0),t[n]+=s)})});let n=Object.entries(t).map(e=>{let[t,n]=e;return{user_id:t,spend:n}});n.sort((e,t)=>t.spend-e.spend);let s=n.slice(0,5);return console.log("topKeys: ".concat(Object.values(s[0]))),s}(e)),c(e)})}catch(e){console.error("There was an error fetching the data",e)}})()},[t,n,r,a,Z,w]),(0,s.jsx)("div",{style:{width:"100%"},children:(0,s.jsxs)(f.Z,{numItems:2,className:"gap-2 p-10 h-[75vh] w-full",children:[(0,s.jsx)(y.Z,{numColSpan:2,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Monthly Spend"}),(0,s.jsx)(F.Z,{data:i,index:"startTime",categories:["spend"],colors:["blue"],valueFormatter:e=>"$ ".concat(new Intl.NumberFormat("us").format(e).toString()),yAxisWidth:100,tickGap:5,customTooltip:eo})]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Top API Keys"}),(0,s.jsx)(F.Z,{className:"mt-4 h-40",data:d,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:80,tickGap:5,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Top Users"}),(0,s.jsx)(F.Z,{className:"mt-4 h-40",data:h,index:"user_id",categories:["spend"],colors:["blue"],yAxisWidth:200,layout:"vertical",showXAxis:!1,showLegend:!1})]})})]})})},ec=()=>{let[e,t]=(0,l.useState)(null),[n,a]=(0,l.useState)(null),o=(0,r.useSearchParams)(),c=o.get("userID"),d=o.get("token"),[m,h]=(0,l.useState)("api-keys"),[u,x]=(0,l.useState)(null);return(0,l.useEffect)(()=>{if(d){let e=(0,q.o)(d);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),x(e.key),e.user_role){let n=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":return"Admin";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",n),t(n)}else console.log("User role not defined");e.user_email?a(e.user_email):console.log("User Email is not set ".concat(e))}}},[d]),(0,s.jsx)(l.Suspense,{fallback:(0,s.jsx)("div",{children:"Loading..."}),children:(0,s.jsxs)("div",{className:"flex flex-col min-h-screen",children:[(0,s.jsx)(i,{userID:c,userRole:e,userEmail:n}),(0,s.jsxs)("div",{className:"flex flex-1 overflow-auto",children:[(0,s.jsx)(ea,{setPage:h}),"api-keys"==m?(0,s.jsx)(G,{userID:c,userRole:e,setUserRole:t,userEmail:n,setUserEmail:a}):"models"==m?(0,s.jsx)($,{userID:c,userRole:e,token:d,accessToken:u}):"llm-playground"==m?(0,s.jsx)(en,{userID:c,userRole:e,token:d,accessToken:u}):(0,s.jsx)(ei,{userID:c,userRole:e,token:d,accessToken:u})]})]})})}}},function(e){e.O(0,[145,971,69,744],function(){return e(e.s=20661)}),_N_E=e.O()}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{20661:function(e,t,n){Promise.resolve().then(n.bind(n,48016))},48016:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return ec}});var s=n(3827),l=n(64090),r=n(47907),a=n(8792),o=n(2179),i=e=>{let{userID:t,userRole:n,userEmail:l}=e;return console.log("User ID:",t),console.log("userEmail:",l),(0,s.jsxs)("nav",{className:"left-0 right-0 top-0 flex justify-between items-center h-12 mb-4",children:[(0,s.jsx)("div",{className:"text-left mx-4 my-2 absolute top-0 left-0",children:(0,s.jsx)("div",{className:"flex flex-col items-center",children:(0,s.jsx)(a.default,{href:"/",children:(0,s.jsx)("button",{className:"text-gray-800 text-2xl px-4 py-1 rounded text-center",children:"\uD83D\uDE85 LiteLLM"})})})}),(0,s.jsx)("div",{className:"text-right mx-4 my-2 absolute top-0 right-0",children:(0,s.jsxs)(o.Z,{variant:"secondary",children:[l,(0,s.jsxs)("p",{children:["Role: ",n]}),(0,s.jsxs)("p",{children:["ID: ",t]})]})})]})},c=n(80588);let d=async(e,t,n)=>{try{if(console.log("Form Values in keyCreateCall:",n),n.description&&(n.metadata||(n.metadata={}),n.metadata.description=n.description,delete n.description,n.metadata=JSON.stringify(n.metadata)),n.metadata){console.log("formValues.metadata:",n.metadata);try{n.metadata=JSON.parse(n.metadata)}catch(e){throw c.ZP.error("Failed to parse metadata: "+e),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",n);let s=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:t,...n})});if(!s.ok){let e=await s.text();throw c.ZP.error("Failed to create key: "+e),console.error("Error response from the server:",e),Error("Network response was not ok")}let l=await s.json();return console.log("API Response:",l),l}catch(e){throw console.error("Failed to create key:",e),e}},m=async(e,t)=>{try{console.log("in keyDeleteCall:",t),c.ZP.info("Making key delete request");let n=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[t]})});if(!n.ok){let e=await n.text();throw c.ZP.error("Failed to delete key: "+e),Error("Network response was not ok")}let s=await n.json();return console.log(s),c.ZP.success("API Key Deleted"),s}catch(e){throw console.error("Failed to create key:",e),e}},h=async(e,t,n)=>{try{let s="/user/info";"App Owner"==n&&(s="".concat(s,"/?user_id=").concat(t)),c.ZP.info("Requesting user data");let l=await fetch(s,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw c.ZP.error(e),Error("Network response was not ok")}let r=await l.json();return c.ZP.info("Received user data"),r}catch(e){throw console.error("Failed to create key:",e),e}},u=async(e,t,n)=>{try{c.ZP.info("Requesting model data");let t=await fetch("/model/info",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw c.ZP.error(e),Error("Network response was not ok")}let n=await t.json();return c.ZP.info("Received model data"),n}catch(e){throw console.error("Failed to create key:",e),e}},x=async(e,t)=>{try{let n="/spend/logs";console.log("in keySpendLogsCall:",n);let s=await fetch("".concat(n,"/?api_key=").concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw c.ZP.error(e),Error("Network response was not ok")}let l=await s.json();return console.log(l),l}catch(e){throw console.error("Failed to create key:",e),e}},p=async(e,t,n,s,l,r)=>{try{let t="/spend/logs";t="App Owner"==n?"".concat(t,"/?user_id=").concat(s,"&start_date=").concat(l,"&end_date=").concat(r):"".concat(t,"/?start_date=").concat(l,"&end_date=").concat(r),c.ZP.info("Making spend logs request");let a=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!a.ok){let e=await a.text();throw c.ZP.error(e),Error("Network response was not ok")}let o=await a.json();return console.log(o),c.ZP.success("Spend Logs received"),o}catch(e){throw console.error("Failed to create key:",e),e}},j=async(e,t)=>{try{let n=await fetch("/key/info",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:t})});if(!n.ok){let e=await n.text();throw c.ZP.error(e),Error("Network response was not ok")}let s=await n.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},g=async(e,t)=>{try{let n="/spend/users";console.log("in spendUsersCall:",n);let s=await fetch("".concat(n,"/?user_id=").concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw c.ZP.error(e),Error("Network response was not ok")}let l=await s.json();return console.log(l),l}catch(e){throw console.error("Failed to get spend for user",e),e}};var y=n(10384),f=n(46453),Z=n(71801),w=n(13969),k=n(12143),_=n(77171),v=n(29714),b=n(88707),S=n(1861);let{Option:N}=w.default;var I=e=>{let{userID:t,userRole:n,accessToken:r,data:a,userModels:i,setData:m}=e,[h]=k.Z.useForm(),[u,x]=(0,l.useState)(!1),[p,j]=(0,l.useState)(null),g=()=>{x(!1),h.resetFields()},I=()=>{x(!1),j(null),h.resetFields()},A=async e=>{try{c.ZP.info("Making API Call"),x(!0);let n=await d(r,t,e);m(e=>e?[...e,n]:[n]),j(n.key),c.ZP.success("API Key Created"),h.resetFields(),localStorage.removeItem("userData"+t)}catch(e){console.error("Error creating the key:",e)}};return(0,s.jsxs)("div",{children:[(0,s.jsx)(o.Z,{className:"mx-auto",onClick:()=>x(!0),children:"+ Create New Key"}),(0,s.jsx)(_.Z,{title:"Create Key",visible:u,width:800,footer:null,onOk:g,onCancel:I,children:(0,s.jsxs)(k.Z,{form:h,onFinish:A,labelCol:{span:6},wrapperCol:{span:16},labelAlign:"left",children:["App Owner"===n||"Admin"===n?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(k.Z.Item,{label:"Key Name",name:"key_alias",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Team ID",name:"team_id",children:(0,s.jsx)(v.Z,{placeholder:"ai_team"})}),(0,s.jsx)(k.Z.Item,{label:"Models",name:"models",children:(0,s.jsx)(w.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:i.map(e=>(0,s.jsx)(N,{value:e,children:e},e))})}),(0,s.jsx)(k.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,s.jsx)(b.Z,{step:.01,precision:2,width:200})}),(0,s.jsx)(k.Z.Item,{label:"Duration (eg: 30s, 30h, 30d)",name:"duration",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Metadata",name:"metadata",children:(0,s.jsx)(v.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(k.Z.Item,{label:"Key Name",name:"key_alias",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Team ID (Contact Group)",name:"team_id",children:(0,s.jsx)(v.Z,{placeholder:"ai_team"})}),(0,s.jsx)(k.Z.Item,{label:"Description",name:"description",children:(0,s.jsx)(v.Z.TextArea,{placeholder:"Enter description",rows:4})})]}),(0,s.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,s.jsx)(S.ZP,{htmlType:"submit",children:"Create Key"})})]})}),p&&(0,s.jsx)(_.Z,{title:"Save your key",visible:u,onOk:g,onCancel:I,footer:null,children:(0,s.jsxs)(f.Z,{numItems:1,className:"gap-2 w-full",children:[(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons, ",(0,s.jsx)("b",{children:"you will not be able to view it again"})," ","through your LiteLLM account. If you lose this secret key, you will need to generate a new one."]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:null!=p?(0,s.jsxs)(Z.Z,{children:["API Key: ",p]}):(0,s.jsx)(Z.Z,{children:"Key being created, this might take 30s"})})]})})]})},A=n(33393),C=n(13810),D=n(61244),T=n(10827),P=n(3851),E=n(2044),O=n(64167),R=n(74480),M=n(7178),U=n(42440),F=n(9853),K=n(67989),L=n(56863),z=e=>{let{token:t,accessToken:n,keySpend:r,keyBudget:a,keyName:i}=e,[c,d]=(0,l.useState)(!1),[m,h]=(0,l.useState)(null),[u,p]=(0,l.useState)(null),j=async()=>{try{if(null==n||null==t)return;console.log("accessToken: ".concat(n,"; token: ").concat(t));let e=await x(n,t);console.log("Response:",e);let s=Object.values(e).reduce((e,t)=>{let n=new Date(t.startTime),s=new Intl.DateTimeFormat("en-US",{day:"2-digit",month:"short"}).format(n);return e[s]=(e[s]||0)+t.spend,e},{}),l=Object.entries(s);l.sort((e,t)=>{let[n]=e,[s]=t,l=new Date(n),r=new Date(s);return l.getTime()-r.getTime()});let r=Object.fromEntries(l);console.log(r);let a=Object.values(e).reduce((e,t)=>{let n=t.user;return e[n]=(e[n]||0)+t.spend,e},{});console.log(s),console.log(a);let o=[];for(let[e,t]of Object.entries(r))o.push({day:e,spend:t});let i=Object.entries(a).sort((e,t)=>t[1]-e[1]).slice(0,5).map(e=>{let[t,n]=e;return{name:t,value:n}});h(o),p(i),console.log("arrayBarChart:",o)}catch(e){console.error("There was an error fetching the data",e)}};return t?(0,s.jsxs)("div",{children:[(0,s.jsx)(o.Z,{className:"mx-auto",onClick:()=>{console.log("Show Modal triggered"),d(!0),j()},children:"View Spend Report"}),(0,s.jsxs)(_.Z,{visible:c,width:1e3,onOk:()=>{d(!1)},onCancel:()=>{d(!1)},footer:null,children:[(0,s.jsxs)(U.Z,{style:{textAlign:"left"},children:["Key Name: ",i]}),(0,s.jsxs)(L.Z,{children:["Monthly Spend $",r]}),(0,s.jsx)(C.Z,{className:"mt-6 mb-6",children:m&&(0,s.jsx)(F.Z,{className:"mt-6",data:m,colors:["green"],index:"day",categories:["spend"],yAxisWidth:48})}),(0,s.jsx)(U.Z,{className:"mt-6",children:"Top 5 Users Spend (USD)"}),(0,s.jsx)(C.Z,{className:"mb-6",children:u&&(0,s.jsx)(K.Z,{className:"mt-6",data:u,color:"teal"})})]})]}):null},B=e=>{let{userID:t,accessToken:n,data:r,setData:a}=e,[i,c]=(0,l.useState)(!1),[d,h]=(0,l.useState)(!1),[u,x]=(0,l.useState)(null),p=async e=>{null!=r&&(x(e),localStorage.removeItem("userData"+t),h(!0))},j=async()=>{if(null!=u&&null!=r){try{await m(n,u);let e=r.filter(e=>e.token!==u);a(e)}catch(e){console.error("Error deleting the key:",e)}h(!1),x(null)}};if(null!=r)return console.log("RERENDER TRIGGERED"),(0,s.jsxs)(C.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4",children:[(0,s.jsx)(U.Z,{children:"API Keys"}),(0,s.jsxs)(T.Z,{className:"mt-5",children:[(0,s.jsx)(O.Z,{children:(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(R.Z,{children:"Key Alias"}),(0,s.jsx)(R.Z,{children:"Secret Key"}),(0,s.jsx)(R.Z,{children:"Spend (USD)"}),(0,s.jsx)(R.Z,{children:"Key Budget (USD)"}),(0,s.jsx)(R.Z,{children:"Team ID"}),(0,s.jsx)(R.Z,{children:"Metadata"}),(0,s.jsx)(R.Z,{children:"Models"}),(0,s.jsx)(R.Z,{children:"TPM / RPM Limits"}),(0,s.jsx)(R.Z,{children:"Expires"})]})}),(0,s.jsx)(P.Z,{children:r.map(e=>(console.log(e),"litellm-dashboard"===e.team_id)?null:(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(E.Z,{children:null!=e.key_alias?(0,s.jsx)(Z.Z,{children:e.key_alias}):(0,s.jsx)(Z.Z,{children:"Not Set"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.key_name})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.spend})}),(0,s.jsx)(E.Z,{children:null!=e.max_budget?(0,s.jsx)(Z.Z,{children:e.max_budget}):(0,s.jsx)(Z.Z,{children:"Unlimited Budget"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.team_id})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:JSON.stringify(e.metadata)})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:JSON.stringify(e.models)})}),(0,s.jsx)(E.Z,{children:(0,s.jsxs)(Z.Z,{children:["TPM Limit: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,s.jsx)("br",{})," RPM Limit:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,s.jsx)(E.Z,{children:null!=e.expires?(0,s.jsx)(Z.Z,{children:e.expires}):(0,s.jsx)(Z.Z,{children:"Never expires"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(D.Z,{onClick:()=>p(e.token),icon:A.Z,size:"sm"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(z,{token:e.token,accessToken:n,keySpend:e.spend,keyBudget:e.max_budget,keyName:e.key_name})})]},e.token))})]}),d&&(0,s.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,s.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,s.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,s.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,s.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,s.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,s.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,s.jsx)("div",{className:"sm:flex sm:items-start",children:(0,s.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,s.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Key"}),(0,s.jsx)("div",{className:"mt-2",children:(0,s.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this key ?"})})]})})}),(0,s.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,s.jsx)(o.Z,{onClick:j,color:"red",className:"ml-2",children:"Delete"}),(0,s.jsx)(o.Z,{onClick:()=>{h(!1),x(null)},children:"Cancel"})]})]})]})})]})},J=e=>{let{userID:t,userSpendData:n,userRole:r,accessToken:a}=e;console.log("User SpendData:",n);let[o,i]=(0,l.useState)(null==n?void 0:n.spend),[c,d]=(0,l.useState)((null==n?void 0:n.max_budget)||null);return(0,l.useEffect)(()=>{(async()=>{if("Admin"===r)try{let e=await g(a,"litellm-proxy-budget");console.log("Result from callSpendUsers:",e);let t=e[0];i(null==t?void 0:t.spend),d((null==t?void 0:t.max_budget)||null)}catch(e){console.error("Failed to get spend for user",e)}})()},[r,a,t]),(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)(C.Z,{className:"mx-auto mb-4",children:[(0,s.jsxs)(L.Z,{children:["$",o]}),(0,s.jsxs)(U.Z,{children:["/ ",null!==c?"$".concat(c," limit"):"No limit"]})]})})},q=n(37963);console.log("isLocal:",!1);var G=e=>{let{userID:t,userRole:n,setUserRole:a,userEmail:o,setUserEmail:i}=e,[c,d]=(0,l.useState)(null),[m,x]=(0,l.useState)(null),p=(0,r.useSearchParams)();p.get("viewSpend"),(0,r.useRouter)();let j=p.get("token"),[g,Z]=(0,l.useState)(null),[w,k]=(0,l.useState)([]);if((0,l.useEffect)(()=>{if(j){let e=(0,q.o)(j);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),Z(e.key),e.user_role){let t=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":return"Admin";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",t),a(t)}else console.log("User role not defined");e.user_email?i(e.user_email):console.log("User Email is not set ".concat(e))}}if(t&&g&&n&&!c){let e=localStorage.getItem("userData"+t),s=localStorage.getItem("userSpendData"+t),l=localStorage.getItem("userModels"+t);e&&s&&l?(d(JSON.parse(e)),x(JSON.parse(s)),k(JSON.parse(l))):(async()=>{try{let e=await h(g,t,n);x(e.user_info),d(e.keys),localStorage.setItem("userData"+t,JSON.stringify(e.keys)),localStorage.setItem("userSpendData"+t,JSON.stringify(e.user_info));let s=await u(g,t,n);console.log("model_info:",s);let l=s.data.map(e=>e.model_name);console.log("available_model_names:",l),k(l),console.log("userModels:",w),localStorage.setItem("userModels"+t,JSON.stringify(l))}catch(e){console.error("There was an error fetching the data",e)}})()}},[t,j,g,c,n]),null==t||null==j){let e="/sso/key/generate";return console.log("Full URL:",e),window.location.href=e,null}return null==g?null:(null==n&&a("App Owner"),(0,s.jsx)("div",{children:(0,s.jsx)(f.Z,{numItems:1,className:"gap-0 p-10 h-[75vh] w-full",children:(0,s.jsxs)(y.Z,{numColSpan:1,children:[(0,s.jsx)(J,{userID:t,userSpendData:m,userRole:n,accessToken:g}),(0,s.jsx)(B,{userID:t,accessToken:g,data:c,setData:d}),(0,s.jsx)(I,{userID:t,userRole:n,userModels:w,accessToken:g,data:c,setData:d})]})})}))},$=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,[o,i]=(0,l.useState)({data:[]});if((0,l.useEffect)(()=>{if(!t||!n||!r||!a)return;let e=async()=>{try{let e=await u(t,a,r);console.log("Model data response:",e.data),i(e)}catch(e){console.error("There was an error fetching the model data",e)}};t&&n&&r&&a&&e()},[t,n,r,a]),!o)return(0,s.jsx)("div",{children:"Loading..."});for(let e=0;e(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(E.Z,{children:(0,s.jsx)(U.Z,{children:e.model_name})}),(0,s.jsx)(E.Z,{children:e.provider}),(0,s.jsx)(E.Z,{children:e.input_cost}),(0,s.jsx)(E.Z,{children:e.output_cost}),(0,s.jsx)(E.Z,{children:e.max_tokens})]},e.model_name))})]})})})})},V=n(92836),W=n(26734),H=n(41608),Y=n(32126),X=n(23682),Q=n(12968),ee=n(67951);async function et(e,t,n,s){console.log("isLocal:",!1);let l=window.location.origin,r=new Q.ZP.OpenAI({apiKey:s,baseURL:l,dangerouslyAllowBrowser:!0});for await(let s of(await r.chat.completions.create({model:n,stream:!0,messages:[{role:"user",content:e}]})))console.log(s),s.choices[0].delta.content&&t(s.choices[0].delta.content)}var en=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,[o,i]=(0,l.useState)(""),[c,d]=(0,l.useState)([]),[m,h]=(0,l.useState)(void 0),[x,p]=(0,l.useState)(null);(0,l.useEffect)(()=>{t&&n&&r&&a&&(async()=>{let e=await u(t,a,r);console.log("model_info:",e),(null==e?void 0:e.data.length)>0&&(p(e),h(e.data[0].model_name))})()},[t,a,r]);let j=(e,t)=>{d(n=>{let s=n[n.length-1];return s&&s.role===e?[...n.slice(0,n.length-1),{role:e,content:s.content+t}]:[...n,{role:e,content:t}]})},g=async()=>{if(""!==o.trim()&&t&&n&&r&&a){d(e=>[...e,{role:"user",content:o}]);try{m&&await et(o,e=>j("assistant",e),m,t)}catch(e){console.error("Error fetching model response",e),j("assistant","Error fetching model response")}i("")}};return(0,s.jsx)("div",{style:{width:"100%",position:"relative"},children:(0,s.jsx)(f.Z,{className:"gap-2 p-10 h-[75vh] w-full",children:(0,s.jsx)(C.Z,{children:(0,s.jsxs)(W.Z,{children:[(0,s.jsxs)(H.Z,{className:"mt-4",children:[(0,s.jsx)(V.Z,{children:"Chat"}),(0,s.jsx)(V.Z,{children:"API Reference"})]}),(0,s.jsxs)(X.Z,{children:[(0,s.jsxs)(Y.Z,{children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{children:"Select Model:"}),(0,s.jsx)("select",{value:m||"",onChange:e=>h(e.target.value),children:null==x?void 0:x.data.map(e=>(0,s.jsx)("option",{value:e.model_name,children:e.model_name},e.model_name))})]}),(0,s.jsxs)(T.Z,{className:"mt-5",style:{display:"block",maxHeight:"60vh",overflowY:"auto"},children:[(0,s.jsx)(O.Z,{children:(0,s.jsx)(M.Z,{children:(0,s.jsx)(E.Z,{children:(0,s.jsx)(U.Z,{children:"Chat"})})})}),(0,s.jsx)(P.Z,{children:c.map((e,t)=>(0,s.jsx)(M.Z,{children:(0,s.jsx)(E.Z,{children:"".concat(e.role,": ").concat(e.content)})},t))})]}),(0,s.jsx)("div",{className:"mt-3",style:{position:"absolute",bottom:5,width:"95%"},children:(0,s.jsxs)("div",{className:"flex",children:[(0,s.jsx)("input",{type:"text",value:o,onChange:e=>i(e.target.value),className:"flex-1 p-2 border rounded-md mr-2",placeholder:"Type your message..."}),(0,s.jsx)("button",{onClick:g,className:"p-2 bg-blue-500 text-white rounded-md",children:"Send"})]})})]}),(0,s.jsx)(Y.Z,{children:(0,s.jsxs)(W.Z,{children:[(0,s.jsxs)(H.Z,{children:[(0,s.jsx)(V.Z,{children:"OpenAI Python SDK"}),(0,s.jsx)(V.Z,{children:"LlamaIndex"}),(0,s.jsx)(V.Z,{children:"Langchain Py"})]}),(0,s.jsxs)(X.Z,{children:[(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nimport openai\nclient = openai.OpenAI(\n api_key="your_api_key",\n base_url="http://0.0.0.0:4000" # proxy base url\n)\n\nresponse = client.chat.completions.create(\n model="gpt-3.5-turbo", # model to use from Models Tab\n messages = [\n {\n "role": "user",\n "content": "this is a test request, write a short poem"\n }\n ],\n extra_body={\n "metadata": {\n "generation_name": "ishaan-generation-openai-client",\n "generation_id": "openai-client-gen-id22",\n "trace_id": "openai-client-trace-id22",\n "trace_user_id": "openai-client-user-id2"\n }\n }\n)\n\nprint(response)\n '})}),(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nimport os, dotenv\n\nfrom llama_index.llms import AzureOpenAI\nfrom llama_index.embeddings import AzureOpenAIEmbedding\nfrom llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\n\nllm = AzureOpenAI(\n engine="azure-gpt-3.5", # model_name on litellm proxy\n temperature=0.0,\n azure_endpoint="http://0.0.0.0:4000", # litellm proxy endpoint\n api_key="sk-1234", # litellm proxy API Key\n api_version="2023-07-01-preview",\n)\n\nembed_model = AzureOpenAIEmbedding(\n deployment_name="azure-embedding-model",\n azure_endpoint="http://0.0.0.0:4000",\n api_key="sk-1234",\n api_version="2023-07-01-preview",\n)\n\n\ndocuments = SimpleDirectoryReader("llama_index_data").load_data()\nservice_context = ServiceContext.from_defaults(llm=llm, embed_model=embed_model)\nindex = VectorStoreIndex.from_documents(documents, service_context=service_context)\n\nquery_engine = index.as_query_engine()\nresponse = query_engine.query("What did the author do growing up?")\nprint(response)\n\n '})}),(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.prompts.chat import (\n ChatPromptTemplate,\n HumanMessagePromptTemplate,\n SystemMessagePromptTemplate,\n)\nfrom langchain.schema import HumanMessage, SystemMessage\n\nchat = ChatOpenAI(\n openai_api_base="http://0.0.0.0:8000",\n model = "gpt-3.5-turbo",\n temperature=0.1,\n extra_body={\n "metadata": {\n "generation_name": "ishaan-generation-langchain-client",\n "generation_id": "langchain-client-gen-id22",\n "trace_id": "langchain-client-trace-id22",\n "trace_user_id": "langchain-client-user-id2"\n }\n }\n)\n\nmessages = [\n SystemMessage(\n content="You are a helpful assistant that im using to make a test request to."\n ),\n HumanMessage(\n content="test from litellm. tell me why it\'s amazing in 1 sentence"\n ),\n]\nresponse = chat(messages)\n\nprint(response)\n\n '})})]})]})})]})]})})})})},es=n(33509),el=n(30569);let{Sider:er}=es.default;var ea=e=>{let{setPage:t}=e;return(0,s.jsx)(es.default,{style:{minHeight:"100vh",maxWidth:"120px"},children:(0,s.jsx)(er,{width:120,children:(0,s.jsxs)(el.Z,{mode:"inline",defaultSelectedKeys:["1"],style:{height:"100%",borderRight:0},children:[(0,s.jsx)(el.Z.Item,{onClick:()=>t("api-keys"),children:"API Keys"},"1"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("models"),children:"Models"},"2"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("llm-playground"),children:"Chat UI"},"3"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("usage"),children:"Usage"},"4")]})})})};let eo=e=>{let{payload:t,active:n}=e;if(!n||!t)return null;let l=t[0].payload,r=l.startTime,a=Object.entries(l.models).map(e=>{let[t,n]=e;return[t,n]});a.sort((e,t)=>t[1]-e[1]);let o=a.slice(0,5);return(0,s.jsxs)("div",{className:"w-56 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown",children:[r,o.map(e=>{let[t,n]=e;return(0,s.jsx)("div",{className:"flex flex-1 space-x-10",children:(0,s.jsx)("div",{className:"p-2",children:(0,s.jsxs)("p",{className:"text-tremor-content text-xs",children:[t,":",(0,s.jsxs)("span",{className:"text-xs text-tremor-content-emphasis",children:[" ",n?n<.01?"<$0.01":n.toFixed(2):""]})]})})},t)})]})};var ei=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,o=new Date,[i,c]=(0,l.useState)([]),[d,m]=(0,l.useState)([]),[h,u]=(0,l.useState)([]),x=new Date(o.getFullYear(),o.getMonth(),1),g=new Date(o.getFullYear(),o.getMonth()+1,0),Z=k(x),w=k(g);function k(e){let t=e.getFullYear(),n=e.getMonth()+1,s=e.getDate();return"".concat(t,"-").concat(n<10?"0"+n:n,"-").concat(s<10?"0"+s:s)}return console.log("Start date is ".concat(Z)),console.log("End date is ".concat(w)),(0,l.useEffect)(()=>{t&&n&&r&&a&&(async()=>{try{await p(t,n,r,a,Z,w).then(async e=>{let n=(await j(t,function(e){let t=[];e.forEach(e=>{Object.entries(e).forEach(e=>{let[n,s]=e;"spend"!==n&&"startTime"!==n&&"models"!==n&&"users"!==n&&t.push({key:n,spend:s})})}),t.sort((e,t)=>Number(t.spend)-Number(e.spend));let n=t.slice(0,5).map(e=>e.key);return console.log("topKeys: ".concat(Object.keys(n[0]))),n}(e))).info.map(e=>({key:(e.key_name||e.key_alias||e.token).substring(0,7),spend:e.spend}));m(n),u(function(e){let t={};e.forEach(e=>{Object.entries(e.users).forEach(e=>{let[n,s]=e;""!==n&&null!=n&&"None"!=n&&(t[n]||(t[n]=0),t[n]+=s)})});let n=Object.entries(t).map(e=>{let[t,n]=e;return{user_id:t,spend:n}});n.sort((e,t)=>t.spend-e.spend);let s=n.slice(0,5);return console.log("topKeys: ".concat(Object.values(s[0]))),s}(e)),c(e)})}catch(e){console.error("There was an error fetching the data",e)}})()},[t,n,r,a,Z,w]),(0,s.jsx)("div",{style:{width:"100%"},children:(0,s.jsxs)(f.Z,{numItems:2,className:"gap-2 p-10 h-[75vh] w-full",children:[(0,s.jsx)(y.Z,{numColSpan:2,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Monthly Spend"}),(0,s.jsx)(F.Z,{data:i,index:"startTime",categories:["spend"],colors:["blue"],valueFormatter:e=>"$ ".concat(new Intl.NumberFormat("us").format(e).toString()),yAxisWidth:100,tickGap:5,customTooltip:eo})]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Top API Keys"}),(0,s.jsx)(F.Z,{className:"mt-4 h-40",data:d,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:80,tickGap:5,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Top Users"}),(0,s.jsx)(F.Z,{className:"mt-4 h-40",data:h,index:"user_id",categories:["spend"],colors:["blue"],yAxisWidth:200,layout:"vertical",showXAxis:!1,showLegend:!1})]})})]})})},ec=()=>{let[e,t]=(0,l.useState)(null),[n,a]=(0,l.useState)(null),o=(0,r.useSearchParams)(),c=o.get("userID"),d=o.get("token"),[m,h]=(0,l.useState)("api-keys"),[u,x]=(0,l.useState)(null);return(0,l.useEffect)(()=>{if(d){let e=(0,q.o)(d);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),x(e.key),e.user_role){let n=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":return"Admin";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",n),t(n)}else console.log("User role not defined");e.user_email?a(e.user_email):console.log("User Email is not set ".concat(e))}}},[d]),(0,s.jsx)(l.Suspense,{fallback:(0,s.jsx)("div",{children:"Loading..."}),children:(0,s.jsxs)("div",{className:"flex flex-col min-h-screen",children:[(0,s.jsx)(i,{userID:c,userRole:e,userEmail:n}),(0,s.jsxs)("div",{className:"flex flex-1 overflow-auto",children:[(0,s.jsx)(ea,{setPage:h}),"api-keys"==m?(0,s.jsx)(G,{userID:c,userRole:e,setUserRole:t,userEmail:n,setUserEmail:a}):"models"==m?(0,s.jsx)($,{userID:c,userRole:e,token:d,accessToken:u}):"llm-playground"==m?(0,s.jsx)(en,{userID:c,userRole:e,token:d,accessToken:u}):(0,s.jsx)(ei,{userID:c,userRole:e,token:d,accessToken:u})]})]})})}}},function(e){e.O(0,[145,971,69,744],function(){return e(e.s=20661)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/lLFQRQnIrRo-GJf5spHEd/_buildManifest.js b/litellm/proxy/_experimental/out/_next/static/unBuvDqydg0yodtP5c3nQ/_buildManifest.js similarity index 100% rename from litellm/proxy/_experimental/out/_next/static/lLFQRQnIrRo-GJf5spHEd/_buildManifest.js rename to litellm/proxy/_experimental/out/_next/static/unBuvDqydg0yodtP5c3nQ/_buildManifest.js diff --git a/litellm/proxy/_experimental/out/_next/static/lLFQRQnIrRo-GJf5spHEd/_ssgManifest.js b/litellm/proxy/_experimental/out/_next/static/unBuvDqydg0yodtP5c3nQ/_ssgManifest.js similarity index 100% rename from litellm/proxy/_experimental/out/_next/static/lLFQRQnIrRo-GJf5spHEd/_ssgManifest.js rename to litellm/proxy/_experimental/out/_next/static/unBuvDqydg0yodtP5c3nQ/_ssgManifest.js diff --git a/litellm/proxy/_experimental/out/index.html b/litellm/proxy/_experimental/out/index.html index f54a24355..80296f4f6 100644 --- a/litellm/proxy/_experimental/out/index.html +++ b/litellm/proxy/_experimental/out/index.html @@ -1 +1 @@ -🚅 LiteLLM \ No newline at end of file +🚅 LiteLLM \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/index.txt b/litellm/proxy/_experimental/out/index.txt index d0cebc66f..b6bb2c868 100644 --- a/litellm/proxy/_experimental/out/index.txt +++ b/litellm/proxy/_experimental/out/index.txt @@ -1,7 +1,7 @@ 2:I[77831,[],""] -3:I[48016,["145","static/chunks/145-9c160ad5539e000f.js","931","static/chunks/app/page-fcb69349f15d154b.js"],""] +3:I[48016,["145","static/chunks/145-9c160ad5539e000f.js","931","static/chunks/app/page-7bb820bd6902dbf2.js"],""] 4:I[5613,[],""] 5:I[31778,[],""] -0:["lLFQRQnIrRo-GJf5spHEd",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/c18941d97fb7245b.css","precedence":"next","crossOrigin":""}]],"$L6"]]]] +0:["unBuvDqydg0yodtP5c3nQ",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/c18941d97fb7245b.css","precedence":"next","crossOrigin":""}]],"$L6"]]]] 6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"🚅 LiteLLM"}],["$","meta","3",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","4",{"rel":"icon","href":"/ui/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]] 1:null diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index afa97dc20..62e134cdc 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -819,6 +819,7 @@ async def _PROXY_track_cost_callback( user_id = user_id or kwargs["litellm_params"]["metadata"].get( "user_api_key_user_id", None ) + team_id = kwargs["litellm_params"]["metadata"].get("user_api_key_team_id", None) if kwargs.get("response_cost", None) is not None: response_cost = kwargs["response_cost"] user_api_key = kwargs["litellm_params"]["metadata"].get( @@ -842,6 +843,7 @@ async def _PROXY_track_cost_callback( token=user_api_key, response_cost=response_cost, user_id=user_id, + team_id=team_id, kwargs=kwargs, completion_response=completion_response, start_time=start_time, @@ -879,6 +881,7 @@ async def update_database( token, response_cost, user_id=None, + team_id=None, kwargs=None, completion_response=None, start_time=None, @@ -886,7 +889,7 @@ async def update_database( ): try: verbose_proxy_logger.info( - f"Enters prisma db call, response_cost: {response_cost}, token: {token}; user_id: {user_id}" + f"Enters prisma db call, response_cost: {response_cost}, token: {token}; user_id: {user_id}; team_id: {team_id}" ) ### [TODO] STEP 1: GET KEY + USER SPEND ### (key, user) @@ -1039,8 +1042,69 @@ async def update_database( except Exception as e: verbose_proxy_logger.info(f"Update Spend Logs DB failed to execute") + ### UPDATE KEY SPEND ### + async def _update_team_db(): + try: + verbose_proxy_logger.debug( + f"adding spend to team db. Response cost: {response_cost}. team_id: {team_id}." + ) + if team_id is None: + verbose_proxy_logger.debug( + "track_cost_callback: team_id is None. Not tracking spend for team" + ) + return + if prisma_client is not None: + # Fetch the existing cost for the given token + existing_spend_obj = await prisma_client.get_data( + team_id=team_id, table_name="team" + ) + verbose_proxy_logger.debug( + f"_update_team_db: existing spend: {existing_spend_obj}" + ) + if existing_spend_obj is None: + existing_spend = 0 + else: + existing_spend = existing_spend_obj.spend + # Calculate the new cost by adding the existing cost and response_cost + new_spend = existing_spend + response_cost + + verbose_proxy_logger.debug(f"new cost: {new_spend}") + # Update the cost column for the given token + await prisma_client.update_data( + team_id=team_id, data={"spend": new_spend}, table_name="team" + ) + + elif custom_db_client is not None: + # Fetch the existing cost for the given token + existing_spend_obj = await custom_db_client.get_data( + key=token, table_name="key" + ) + verbose_proxy_logger.debug( + f"_update_key_db existing spend: {existing_spend_obj}" + ) + if existing_spend_obj is None: + existing_spend = 0 + else: + existing_spend = existing_spend_obj.spend + # Calculate the new cost by adding the existing cost and response_cost + new_spend = existing_spend + response_cost + + verbose_proxy_logger.debug(f"new cost: {new_spend}") + # Update the cost column for the given token + await custom_db_client.update_data( + key=token, value={"spend": new_spend}, table_name="key" + ) + + valid_token = user_api_key_cache.get_cache(key=token) + if valid_token is not None: + valid_token.spend = new_spend + user_api_key_cache.set_cache(key=token, value=valid_token) + except Exception as e: + verbose_proxy_logger.info(f"Update Team DB failed to execute") + asyncio.create_task(_update_user_db()) asyncio.create_task(_update_key_db()) + asyncio.create_task(_update_team_db()) asyncio.create_task(_insert_spend_log_to_db()) verbose_proxy_logger.info("Successfully updated spend in all 3 tables") except Exception as e: @@ -2143,6 +2207,9 @@ async def completion( data["metadata"]["user_api_key"] = user_api_key_dict.api_key data["metadata"]["user_api_key_metadata"] = user_api_key_dict.metadata data["metadata"]["user_api_key_user_id"] = user_api_key_dict.user_id + data["metadata"]["user_api_key_team_id"] = getattr( + user_api_key_dict, "team_id", None + ) _headers = dict(request.headers) _headers.pop( "authorization", None @@ -2306,6 +2373,9 @@ async def chat_completion( data["metadata"] = {} data["metadata"]["user_api_key"] = user_api_key_dict.api_key data["metadata"]["user_api_key_user_id"] = user_api_key_dict.user_id + data["metadata"]["user_api_key_team_id"] = getattr( + user_api_key_dict, "team_id", None + ) data["metadata"]["user_api_key_metadata"] = user_api_key_dict.metadata _headers = dict(request.headers) _headers.pop( @@ -2527,6 +2597,9 @@ async def embeddings( ) # do not store the original `sk-..` api key in the db data["metadata"]["headers"] = _headers data["metadata"]["user_api_key_user_id"] = user_api_key_dict.user_id + data["metadata"]["user_api_key_team_id"] = getattr( + user_api_key_dict, "team_id", None + ) data["metadata"]["endpoint"] = str(request.url) ### TEAM-SPECIFIC PARAMS ### @@ -2698,6 +2771,9 @@ async def image_generation( ) # do not store the original `sk-..` api key in the db data["metadata"]["headers"] = _headers data["metadata"]["user_api_key_user_id"] = user_api_key_dict.user_id + data["metadata"]["user_api_key_team_id"] = getattr( + user_api_key_dict, "team_id", None + ) data["metadata"]["endpoint"] = str(request.url) ### TEAM-SPECIFIC PARAMS ### @@ -2853,6 +2929,9 @@ async def moderations( ) # do not store the original `sk-..` api key in the db data["metadata"]["headers"] = _headers data["metadata"]["user_api_key_user_id"] = user_api_key_dict.user_id + data["metadata"]["user_api_key_team_id"] = getattr( + user_api_key_dict, "team_id", None + ) data["metadata"]["endpoint"] = str(request.url) ### TEAM-SPECIFIC PARAMS ### @@ -4208,6 +4287,9 @@ async def async_queue_request( ) # do not store the original `sk-..` api key in the db data["metadata"]["headers"] = _headers data["metadata"]["user_api_key_user_id"] = user_api_key_dict.user_id + data["metadata"]["user_api_key_team_id"] = getattr( + user_api_key_dict, "team_id", None + ) data["metadata"]["endpoint"] = str(request.url) global user_temperature, user_request_timeout, user_max_tokens, user_api_base diff --git a/litellm/proxy/utils.py b/litellm/proxy/utils.py index d3c95f350..b14727d1a 100644 --- a/litellm/proxy/utils.py +++ b/litellm/proxy/utils.py @@ -808,8 +808,9 @@ class PrismaClient: data: dict = {}, data_list: Optional[List] = None, user_id: Optional[str] = None, + team_id: Optional[str] = None, query_type: Literal["update", "update_many"] = "update", - table_name: Optional[Literal["user", "key", "config", "spend"]] = None, + table_name: Optional[Literal["user", "key", "config", "spend", "team"]] = None, update_key_values: Optional[dict] = None, ): """ @@ -860,6 +861,35 @@ class PrismaClient: + "\033[0m" ) return {"user_id": user_id, "data": db_data} + elif ( + team_id is not None + or (table_name is not None and table_name == "team") + and query_type == "update" + ): + """ + If data['spend'] + data['user'], update the user table with spend info as well + """ + if team_id is None: + team_id = db_data["team_id"] + if update_key_values is None: + update_key_values = db_data + if "team_id" not in db_data and team_id is not None: + db_data["team_id"] = team_id + update_team_row = await self.db.litellm_teamtable.upsert( + where={"team_id": team_id}, # type: ignore + data={ + "create": {**db_data}, # type: ignore + "update": { + **update_key_values # type: ignore + }, # just update user-specified values, if it already exists + }, + ) + verbose_proxy_logger.info( + "\033[91m" + + f"DB Team Table - update succeeded {update_team_row}" + + "\033[0m" + ) + return {"team_id": team_id, "data": db_data} elif ( table_name is not None and table_name == "key" diff --git a/litellm/tests/test_custom_api_logger.py b/litellm/tests/test_custom_api_logger.py new file mode 100644 index 000000000..bddce9a08 --- /dev/null +++ b/litellm/tests/test_custom_api_logger.py @@ -0,0 +1,46 @@ +import sys +import os +import io, asyncio + +# import logging +# logging.basicConfig(level=logging.DEBUG) +sys.path.insert(0, os.path.abspath("../..")) +print("Modified sys.path:", sys.path) + + +from litellm import completion +import litellm + +litellm.num_retries = 3 + +import time, random +import pytest + + +@pytest.mark.asyncio +@pytest.mark.skip(reason="new beta feature, will be testing in our ci/cd soon") +async def test_custom_api_logging(): + try: + litellm.success_callback = ["generic"] + litellm.set_verbose = True + os.environ["GENERIC_LOGGER_ENDPOINT"] = "http://localhost:8000/log-event" + + print("Testing generic api logging") + + await litellm.acompletion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": f"This is a test"}], + max_tokens=10, + temperature=0.7, + user="ishaan-2", + ) + + except Exception as e: + pytest.fail(f"An exception occurred - {e}") + finally: + # post, close log file and verify + # Reset stdout to the original value + print("Passed! Testing async s3 logging") + + +# test_s3_logging() diff --git a/litellm/utils.py b/litellm/utils.py index 93e934d4c..2e54b5e44 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -44,9 +44,9 @@ except: filename = str( resources.files(litellm).joinpath("llms/tokenizers") # for python 3.10 ) # for python 3.10+ -os.environ["TIKTOKEN_CACHE_DIR"] = ( - filename # use local copy of tiktoken b/c of - https://github.com/BerriAI/litellm/issues/1071 -) +os.environ[ + "TIKTOKEN_CACHE_DIR" +] = filename # use local copy of tiktoken b/c of - https://github.com/BerriAI/litellm/issues/1071 encoding = tiktoken.get_encoding("cl100k_base") import importlib.metadata @@ -4256,7 +4256,14 @@ def get_optional_params( optional_params["stop_sequences"] = stop if max_tokens is not None: optional_params["max_output_tokens"] = max_tokens - elif custom_llm_provider == "vertex_ai": + elif custom_llm_provider == "vertex_ai" and model in ( + litellm.vertex_chat_models + or model in litellm.vertex_code_chat_models + or model in litellm.vertex_text_models + or model in litellm.vertex_code_text_models + or model in litellm.vertex_language_models + or model in litellm.vertex_embedding_models + ): ## check if unsupported param passed in supported_params = [ "temperature", diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 7a7f154e3..fa50b06f1 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -642,21 +642,40 @@ "mode": "chat" }, "gemini-pro": { - "max_tokens": 30720, + "max_tokens": 32760, "max_output_tokens": 2048, "input_cost_per_token": 0.00000025, "output_cost_per_token": 0.0000005, "litellm_provider": "vertex_ai-language-models", "mode": "chat" }, + "gemini-1.0-pro": { + "max_tokens": 32760, + "max_output_tokens": 8192, + "input_cost_per_token": 0.00000025, + "output_cost_per_token": 0.0000005, + "litellm_provider": "vertex_ai-language-models", + "mode": "chat" + }, "gemini-pro-vision": { - "max_tokens": 30720, + "max_tokens": 16384, "max_output_tokens": 2048, "input_cost_per_token": 0.00000025, "output_cost_per_token": 0.0000005, "litellm_provider": "vertex_ai-vision-models", "mode": "chat" }, + "gemini-1.0-pro-vision": { + "max_tokens": 16384, + "max_output_tokens": 2048, + "max_images_per_prompt": 16, + "max_videos_per_prompt": 1, + "max_video_length": 2, + "input_cost_per_token": 0.00000025, + "output_cost_per_token": 0.0000005, + "litellm_provider": "vertex_ai-vision-models", + "mode": "chat" + }, "textembedding-gecko": { "max_tokens": 3072, "max_input_tokens": 3072, diff --git a/pyproject.toml b/pyproject.toml index bb64ff0a8..04667a88f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "litellm" -version = "1.24.0" +version = "1.24.3" description = "Library to easily interface with LLM API providers" authors = ["BerriAI"] license = "MIT" @@ -69,7 +69,7 @@ requires = ["poetry-core", "wheel"] build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "1.24.0" +version = "1.24.3" version_files = [ "pyproject.toml:^version" ] diff --git a/ui/litellm-dashboard/out/404.html b/ui/litellm-dashboard/out/404.html index 68e7eafd9..03563194a 100644 --- a/ui/litellm-dashboard/out/404.html +++ b/ui/litellm-dashboard/out/404.html @@ -1 +1 @@ -404: This page could not be found.🚅 LiteLLM

404

This page could not be found.

\ No newline at end of file +404: This page could not be found.🚅 LiteLLM

404

This page could not be found.

\ No newline at end of file diff --git a/ui/litellm-dashboard/out/_next/static/chunks/app/page-fcb69349f15d154b.js b/ui/litellm-dashboard/out/_next/static/chunks/app/page-7bb820bd6902dbf2.js similarity index 62% rename from ui/litellm-dashboard/out/_next/static/chunks/app/page-fcb69349f15d154b.js rename to ui/litellm-dashboard/out/_next/static/chunks/app/page-7bb820bd6902dbf2.js index ae2f60d88..5402c8d1f 100644 --- a/ui/litellm-dashboard/out/_next/static/chunks/app/page-fcb69349f15d154b.js +++ b/ui/litellm-dashboard/out/_next/static/chunks/app/page-7bb820bd6902dbf2.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{20661:function(e,t,n){Promise.resolve().then(n.bind(n,48016))},48016:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return ec}});var s=n(3827),l=n(64090),r=n(47907),a=n(8792),o=n(2179),i=e=>{let{userID:t,userRole:n,userEmail:l}=e;return console.log("User ID:",t),console.log("userEmail:",l),(0,s.jsxs)("nav",{className:"left-0 right-0 top-0 flex justify-between items-center h-12 mb-4",children:[(0,s.jsx)("div",{className:"text-left mx-4 my-2 absolute top-0 left-0",children:(0,s.jsx)("div",{className:"flex flex-col items-center",children:(0,s.jsx)(a.default,{href:"/",children:(0,s.jsx)("button",{className:"text-gray-800 text-2xl px-4 py-1 rounded text-center",children:"\uD83D\uDE85 LiteLLM"})})})}),(0,s.jsx)("div",{className:"text-right mx-4 my-2 absolute top-0 right-0",children:(0,s.jsxs)(o.Z,{variant:"secondary",children:[l,(0,s.jsxs)("p",{children:["Role: ",n]}),(0,s.jsxs)("p",{children:["ID: ",t]})]})})]})},c=n(80588);let d=async(e,t,n)=>{try{if(console.log("Form Values in keyCreateCall:",n),n.description&&(n.metadata||(n.metadata={}),n.metadata.description=n.description,delete n.description,n.metadata=JSON.stringify(n.metadata)),n.metadata){console.log("formValues.metadata:",n.metadata);try{n.metadata=JSON.parse(n.metadata)}catch(e){throw c.ZP.error("Failed to parse metadata: "+e),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",n);let s=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:t,...n})});if(!s.ok){let e=await s.text();throw c.ZP.error("Failed to create key: "+e),console.error("Error response from the server:",e),Error("Network response was not ok")}let l=await s.json();return console.log("API Response:",l),l}catch(e){throw console.error("Failed to create key:",e),e}},m=async(e,t)=>{try{console.log("in keyDeleteCall:",t),c.ZP.info("Making key delete request");let n=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[t]})});if(!n.ok){let e=await n.text();throw c.ZP.error("Failed to delete key: "+e),Error("Network response was not ok")}let s=await n.json();return console.log(s),c.ZP.success("API Key Deleted"),s}catch(e){throw console.error("Failed to create key:",e),e}},h=async(e,t,n)=>{try{let s="/user/info";"App Owner"==n&&(s="".concat(s,"/?user_id=").concat(t)),c.ZP.info("Requesting user data");let l=await fetch(s,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw c.ZP.error(e),Error("Network response was not ok")}let r=await l.json();return c.ZP.info("Received user data"),r}catch(e){throw console.error("Failed to create key:",e),e}},u=async(e,t,n)=>{try{c.ZP.info("Requesting model data");let t=await fetch("/model/info",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw c.ZP.error(e),Error("Network response was not ok")}let n=await t.json();return c.ZP.info("Received model data"),n}catch(e){throw console.error("Failed to create key:",e),e}},x=async(e,t)=>{try{let n="/spend/logs";console.log("in keySpendLogsCall:",n);let s=await fetch("".concat(n,"/?api_key=").concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw c.ZP.error(e),Error("Network response was not ok")}let l=await s.json();return console.log(l),l}catch(e){throw console.error("Failed to create key:",e),e}},p=async(e,t,n,s,l,r)=>{try{let t="/spend/logs";t="App Owner"==n?"".concat(t,"/?user_id=").concat(s,"&start_date=").concat(l,"&end_date=").concat(r):"".concat(t,"/?start_date=").concat(l,"&end_date=").concat(r),c.ZP.info("Making spend logs request");let a=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!a.ok){let e=await a.text();throw c.ZP.error(e),Error("Network response was not ok")}let o=await a.json();return console.log(o),c.ZP.success("Spend Logs received"),o}catch(e){throw console.error("Failed to create key:",e),e}},j=async(e,t)=>{try{let n=await fetch("/key/info",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:t})});if(!n.ok){let e=await n.text();throw c.ZP.error(e),Error("Network response was not ok")}let s=await n.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},g=async(e,t)=>{try{let n="/spend/users";console.log("in spendUsersCall:",n);let s=await fetch("".concat(n,"/?user_id=").concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw c.ZP.error(e),Error("Network response was not ok")}let l=await s.json();return console.log(l),l}catch(e){throw console.error("Failed to get spend for user",e),e}};var y=n(10384),f=n(46453),Z=n(71801),w=n(13969),k=n(12143),_=n(77171),v=n(29714),b=n(88707),S=n(1861);let{Option:N}=w.default;var I=e=>{let{userID:t,userRole:n,accessToken:r,data:a,userModels:i,setData:m}=e,[h]=k.Z.useForm(),[u,x]=(0,l.useState)(!1),[p,j]=(0,l.useState)(null),g=()=>{x(!1),h.resetFields()},I=()=>{x(!1),j(null),h.resetFields()},A=async e=>{try{c.ZP.info("Making API Call"),x(!0);let n=await d(r,t,e);m(e=>e?[...e,n]:[n]),j(n.key),c.ZP.success("API Key Created"),h.resetFields(),localStorage.removeItem("userData"+t)}catch(e){console.error("Error creating the key:",e)}};return(0,s.jsxs)("div",{children:[(0,s.jsx)(o.Z,{className:"mx-auto",onClick:()=>x(!0),children:"+ Create New Key"}),(0,s.jsx)(_.Z,{title:"Create Key",visible:u,width:800,footer:null,onOk:g,onCancel:I,children:(0,s.jsxs)(k.Z,{form:h,onFinish:A,labelCol:{span:6},wrapperCol:{span:16},labelAlign:"left",children:["App Owner"===n||"Admin"===n?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(k.Z.Item,{label:"Key Name",name:"key_alias",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Team ID",name:"team_id",children:(0,s.jsx)(v.Z,{placeholder:"ai_team"})}),(0,s.jsx)(k.Z.Item,{label:"Models",name:"models",children:(0,s.jsx)(w.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:i.map(e=>(0,s.jsx)(N,{value:e,children:e},e))})}),(0,s.jsx)(k.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,s.jsx)(b.Z,{step:.01,precision:2,width:200})}),(0,s.jsx)(k.Z.Item,{label:"Duration (eg: 30s, 30h, 30d)",name:"duration",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Metadata",name:"metadata",children:(0,s.jsx)(v.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(k.Z.Item,{label:"Key Name",name:"key_alias",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Team ID (Contact Group)",name:"team_id",children:(0,s.jsx)(v.Z,{placeholder:"ai_team"})}),(0,s.jsx)(k.Z.Item,{label:"Description",name:"description",children:(0,s.jsx)(v.Z.TextArea,{placeholder:"Enter description",rows:4})})]}),(0,s.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,s.jsx)(S.ZP,{htmlType:"submit",children:"Create Key"})})]})}),p&&(0,s.jsx)(_.Z,{title:"Save your key",visible:u,onOk:g,onCancel:I,footer:null,children:(0,s.jsxs)(f.Z,{numItems:1,className:"gap-2 w-full",children:[(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons, ",(0,s.jsx)("b",{children:"you will not be able to view it again"})," ","through your LiteLLM account. If you lose this secret key, you will need to generate a new one."]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:null!=p?(0,s.jsxs)(Z.Z,{children:["API Key: ",p]}):(0,s.jsx)(Z.Z,{children:"Key being created, this might take 30s"})})]})})]})},A=n(33393),C=n(13810),D=n(61244),T=n(10827),P=n(3851),E=n(2044),O=n(64167),R=n(74480),M=n(7178),U=n(42440),F=n(9853),K=n(67989),L=n(56863),z=e=>{let{token:t,accessToken:n,keySpend:r,keyBudget:a,keyName:i}=e,[c,d]=(0,l.useState)(!1),[m,h]=(0,l.useState)(null),[u,p]=(0,l.useState)(null),j=async()=>{try{if(null==n||null==t)return;console.log("accessToken: ".concat(n,"; token: ").concat(t));let e=await x(n,t);console.log("Response:",e);let s=Object.values(e).reduce((e,t)=>{let n=new Date(t.startTime),s=new Intl.DateTimeFormat("en-US",{day:"2-digit",month:"short"}).format(n);return e[s]=(e[s]||0)+t.spend,e},{}),l=Object.entries(s);l.sort((e,t)=>{let[n]=e,[s]=t,l=new Date(n),r=new Date(s);return l.getTime()-r.getTime()});let r=Object.fromEntries(l);console.log(r);let a=Object.values(e).reduce((e,t)=>{let n=t.user;return e[n]=(e[n]||0)+t.spend,e},{});console.log(s),console.log(a);let o=[];for(let[e,t]of Object.entries(r))o.push({day:e,spend:t});let i=Object.entries(a).sort((e,t)=>t[1]-e[1]).slice(0,5).map(e=>{let[t,n]=e;return{name:t,value:n}});h(o),p(i),console.log("arrayBarChart:",o)}catch(e){console.error("There was an error fetching the data",e)}};return t?(0,s.jsxs)("div",{children:[(0,s.jsx)(o.Z,{className:"mx-auto",onClick:()=>{console.log("Show Modal triggered"),d(!0),j()},children:"View Spend Report"}),(0,s.jsxs)(_.Z,{visible:c,width:1e3,onOk:()=>{d(!1)},onCancel:()=>{d(!1)},footer:null,children:[(0,s.jsxs)(U.Z,{style:{textAlign:"left"},children:["Key Name: ",i]}),(0,s.jsxs)(L.Z,{children:["Monthly Spend $",r]}),(0,s.jsx)(C.Z,{className:"mt-6 mb-6",children:m&&(0,s.jsx)(F.Z,{className:"mt-6",data:m,colors:["green"],index:"day",categories:["spend"],yAxisWidth:48})}),(0,s.jsx)(U.Z,{className:"mt-6",children:"Top 5 Users Spend (USD)"}),(0,s.jsx)(C.Z,{className:"mb-6",children:u&&(0,s.jsx)(K.Z,{className:"mt-6",data:u,color:"teal"})})]})]}):null},B=e=>{let{userID:t,accessToken:n,data:r,setData:a}=e,[i,c]=(0,l.useState)(!1),[d,h]=(0,l.useState)(!1),[u,x]=(0,l.useState)(null),p=async e=>{null!=r&&(x(e),localStorage.removeItem("userData"+t),h(!0))},j=async()=>{if(null!=u&&null!=r){try{await m(n,u);let e=r.filter(e=>e.token!==u);a(e)}catch(e){console.error("Error deleting the key:",e)}h(!1),x(null)}};if(null!=r)return console.log("RERENDER TRIGGERED"),(0,s.jsxs)(C.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4",children:[(0,s.jsx)(U.Z,{children:"API Keys"}),(0,s.jsxs)(T.Z,{className:"mt-5",children:[(0,s.jsx)(O.Z,{children:(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(R.Z,{children:"Key Alias"}),(0,s.jsx)(R.Z,{children:"Secret Key"}),(0,s.jsx)(R.Z,{children:"Spend (USD)"}),(0,s.jsx)(R.Z,{children:"Key Budget (USD)"}),(0,s.jsx)(R.Z,{children:"Team ID"}),(0,s.jsx)(R.Z,{children:"Metadata"}),(0,s.jsx)(R.Z,{children:"Models"}),(0,s.jsx)(R.Z,{children:"TPM / RPM Limits"}),(0,s.jsx)(R.Z,{children:"Expires"})]})}),(0,s.jsx)(P.Z,{children:r.map(e=>(console.log(e),"litellm-dashboard"===e.team_id)?null:(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(E.Z,{children:null!=e.key_alias?(0,s.jsx)(Z.Z,{children:e.key_alias}):(0,s.jsx)(Z.Z,{children:"Not Set"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.key_name})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.spend})}),(0,s.jsx)(E.Z,{children:null!=e.max_budget?(0,s.jsx)(Z.Z,{children:e.max_budget}):(0,s.jsx)(Z.Z,{children:"Unlimited Budget"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.team_id})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:JSON.stringify(e.metadata)})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:JSON.stringify(e.models)})}),(0,s.jsx)(E.Z,{children:(0,s.jsxs)(Z.Z,{children:["TPM Limit: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,s.jsx)("br",{})," RPM Limit:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,s.jsx)(E.Z,{children:null!=e.expires?(0,s.jsx)(Z.Z,{children:e.expires}):(0,s.jsx)(Z.Z,{children:"Never expires"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(D.Z,{onClick:()=>p(e.token),icon:A.Z,size:"sm"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(z,{token:e.token,accessToken:n,keySpend:e.spend,keyBudget:e.max_budget,keyName:e.key_name})})]},e.token))})]}),d&&(0,s.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,s.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,s.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,s.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,s.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,s.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,s.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,s.jsx)("div",{className:"sm:flex sm:items-start",children:(0,s.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,s.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Key"}),(0,s.jsx)("div",{className:"mt-2",children:(0,s.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this key ?"})})]})})}),(0,s.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,s.jsx)(o.Z,{onClick:j,color:"red",className:"ml-2",children:"Delete"}),(0,s.jsx)(o.Z,{onClick:()=>{h(!1),x(null)},children:"Cancel"})]})]})]})})]})},J=e=>{let{userID:t,userSpendData:n,userRole:r,accessToken:a}=e;console.log("User SpendData:",n);let[o,i]=(0,l.useState)(null==n?void 0:n.spend),[c,d]=(0,l.useState)((null==n?void 0:n.max_budget)||null);return(0,l.useEffect)(()=>{(async()=>{if("Admin"===r)try{let e=await g(a,"litellm-proxy-budget");console.log("Result from callSpendUsers:",e);let t=e[0];i(null==t?void 0:t.spend),d((null==t?void 0:t.max_budget)||null)}catch(e){console.error("Failed to get spend for user",e)}})()},[r,a,t]),(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)(C.Z,{className:"mx-auto mb-4",children:[(0,s.jsxs)(L.Z,{children:["$",o]}),(0,s.jsxs)(U.Z,{children:["/ ",null!==c?"$".concat(c," limit"):"No limit"]})]})})},q=n(37963);console.log("isLocal:",!1);var G=e=>{let{userID:t,userRole:n,setUserRole:a,userEmail:o,setUserEmail:i}=e,[c,d]=(0,l.useState)(null),[m,x]=(0,l.useState)(null),p=(0,r.useSearchParams)();p.get("viewSpend"),(0,r.useRouter)();let j=p.get("token"),[g,Z]=(0,l.useState)(null),[w,k]=(0,l.useState)([]);if((0,l.useEffect)(()=>{if(j){let e=(0,q.o)(j);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),Z(e.key),e.user_role){let t=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":return"Admin";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",t),a(t)}else console.log("User role not defined");e.user_email?i(e.user_email):console.log("User Email is not set ".concat(e))}}if(t&&g&&n&&!c){let e=localStorage.getItem("userData"+t),s=localStorage.getItem("userSpendData"+t),l=localStorage.getItem("userModels"+t);e&&s&&l?(d(JSON.parse(e)),x(JSON.parse(s)),k(JSON.parse(l))):(async()=>{try{let e=await h(g,t,n);x(e.user_info),d(e.keys),localStorage.setItem("userData"+t,JSON.stringify(e.keys)),localStorage.setItem("userSpendData"+t,JSON.stringify(e.user_info));let s=await u(g,t,n);console.log("model_info:",s);let l=s.data.map(e=>e.model_name);console.log("available_model_names:",l),k(l),console.log("userModels:",w),localStorage.setItem("userModels"+t,JSON.stringify(l))}catch(e){console.error("There was an error fetching the data",e)}})()}},[t,j,g,c,n]),null==t||null==j){let e="/sso/key/generate";return console.log("Full URL:",e),window.location.href=e,null}return null==g?null:(null==n&&a("App Owner"),(0,s.jsx)("div",{children:(0,s.jsx)(f.Z,{numItems:1,className:"gap-0 p-10 h-[75vh] w-full",children:(0,s.jsxs)(y.Z,{numColSpan:1,children:[(0,s.jsx)(J,{userID:t,userSpendData:m,userRole:n,accessToken:g}),(0,s.jsx)(B,{userID:t,accessToken:g,data:c,setData:d}),(0,s.jsx)(I,{userID:t,userRole:n,userModels:w,accessToken:g,data:c,setData:d})]})})}))},$=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,[o,i]=(0,l.useState)({data:[]});if((0,l.useEffect)(()=>{if(!t||!n||!r||!a)return;let e=async()=>{try{let e=await u(t,a,r);console.log("Model data response:",e.data),i(e)}catch(e){console.error("There was an error fetching the model data",e)}};t&&n&&r&&a&&e()},[t,n,r,a]),!o)return(0,s.jsx)("div",{children:"Loading..."});for(let e=0;e(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(E.Z,{children:(0,s.jsx)(U.Z,{children:e.model_name})}),(0,s.jsx)(E.Z,{children:e.provider}),(0,s.jsx)(E.Z,{children:e.input_cost}),(0,s.jsx)(E.Z,{children:e.output_cost}),(0,s.jsx)(E.Z,{children:e.max_tokens})]},e.model_name))})]})})})})},V=n(92836),W=n(26734),H=n(41608),Y=n(32126),X=n(23682),Q=n(12968),ee=n(67951);async function et(e,t,n,s){let l=new Q.ZP.OpenAI({apiKey:s,baseURL:"http://0.0.0.0:4000",dangerouslyAllowBrowser:!0});for await(let s of(await l.chat.completions.create({model:n,stream:!0,messages:[{role:"user",content:e}]})))console.log(s),s.choices[0].delta.content&&t(s.choices[0].delta.content)}var en=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,[o,i]=(0,l.useState)(""),[c,d]=(0,l.useState)([]),[m,h]=(0,l.useState)(void 0),[x,p]=(0,l.useState)(null);(0,l.useEffect)(()=>{t&&n&&r&&a&&(async()=>{let e=await u(t,a,r);console.log("model_info:",e),(null==e?void 0:e.data.length)>0&&(p(e),h(e.data[0].model_name))})()},[t,a,r]);let j=(e,t)=>{d(n=>{let s=n[n.length-1];return s&&s.role===e?[...n.slice(0,n.length-1),{role:e,content:s.content+t}]:[...n,{role:e,content:t}]})},g=async()=>{if(""!==o.trim()&&t&&n&&r&&a){d(e=>[...e,{role:"user",content:o}]);try{m&&await et(o,e=>j("assistant",e),m,t)}catch(e){console.error("Error fetching model response",e),j("assistant","Error fetching model response")}i("")}};return(0,s.jsx)("div",{style:{width:"100%",position:"relative"},children:(0,s.jsx)(f.Z,{className:"gap-2 p-10 h-[75vh] w-full",children:(0,s.jsx)(C.Z,{children:(0,s.jsxs)(W.Z,{children:[(0,s.jsxs)(H.Z,{className:"mt-4",children:[(0,s.jsx)(V.Z,{children:"Chat"}),(0,s.jsx)(V.Z,{children:"API Reference"})]}),(0,s.jsxs)(X.Z,{children:[(0,s.jsxs)(Y.Z,{children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{children:"Select Model:"}),(0,s.jsx)("select",{value:m||"",onChange:e=>h(e.target.value),children:null==x?void 0:x.data.map(e=>(0,s.jsx)("option",{value:e.model_name,children:e.model_name},e.model_name))})]}),(0,s.jsxs)(T.Z,{className:"mt-5",style:{display:"block",maxHeight:"60vh",overflowY:"auto"},children:[(0,s.jsx)(O.Z,{children:(0,s.jsx)(M.Z,{children:(0,s.jsx)(E.Z,{children:(0,s.jsx)(U.Z,{children:"Chat"})})})}),(0,s.jsx)(P.Z,{children:c.map((e,t)=>(0,s.jsx)(M.Z,{children:(0,s.jsx)(E.Z,{children:"".concat(e.role,": ").concat(e.content)})},t))})]}),(0,s.jsx)("div",{className:"mt-3",style:{position:"absolute",bottom:5,width:"95%"},children:(0,s.jsxs)("div",{className:"flex",children:[(0,s.jsx)("input",{type:"text",value:o,onChange:e=>i(e.target.value),className:"flex-1 p-2 border rounded-md mr-2",placeholder:"Type your message..."}),(0,s.jsx)("button",{onClick:g,className:"p-2 bg-blue-500 text-white rounded-md",children:"Send"})]})})]}),(0,s.jsx)(Y.Z,{children:(0,s.jsxs)(W.Z,{children:[(0,s.jsxs)(H.Z,{children:[(0,s.jsx)(V.Z,{children:"OpenAI Python SDK"}),(0,s.jsx)(V.Z,{children:"LlamaIndex"}),(0,s.jsx)(V.Z,{children:"Langchain Py"})]}),(0,s.jsxs)(X.Z,{children:[(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nimport openai\nclient = openai.OpenAI(\n api_key="your_api_key",\n base_url="http://0.0.0.0:4000" # proxy base url\n)\n\nresponse = client.chat.completions.create(\n model="gpt-3.5-turbo", # model to use from Models Tab\n messages = [\n {\n "role": "user",\n "content": "this is a test request, write a short poem"\n }\n ],\n extra_body={\n "metadata": {\n "generation_name": "ishaan-generation-openai-client",\n "generation_id": "openai-client-gen-id22",\n "trace_id": "openai-client-trace-id22",\n "trace_user_id": "openai-client-user-id2"\n }\n }\n)\n\nprint(response)\n '})}),(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nimport os, dotenv\n\nfrom llama_index.llms import AzureOpenAI\nfrom llama_index.embeddings import AzureOpenAIEmbedding\nfrom llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\n\nllm = AzureOpenAI(\n engine="azure-gpt-3.5", # model_name on litellm proxy\n temperature=0.0,\n azure_endpoint="http://0.0.0.0:4000", # litellm proxy endpoint\n api_key="sk-1234", # litellm proxy API Key\n api_version="2023-07-01-preview",\n)\n\nembed_model = AzureOpenAIEmbedding(\n deployment_name="azure-embedding-model",\n azure_endpoint="http://0.0.0.0:4000",\n api_key="sk-1234",\n api_version="2023-07-01-preview",\n)\n\n\ndocuments = SimpleDirectoryReader("llama_index_data").load_data()\nservice_context = ServiceContext.from_defaults(llm=llm, embed_model=embed_model)\nindex = VectorStoreIndex.from_documents(documents, service_context=service_context)\n\nquery_engine = index.as_query_engine()\nresponse = query_engine.query("What did the author do growing up?")\nprint(response)\n\n '})}),(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.prompts.chat import (\n ChatPromptTemplate,\n HumanMessagePromptTemplate,\n SystemMessagePromptTemplate,\n)\nfrom langchain.schema import HumanMessage, SystemMessage\n\nchat = ChatOpenAI(\n openai_api_base="http://0.0.0.0:8000",\n model = "gpt-3.5-turbo",\n temperature=0.1,\n extra_body={\n "metadata": {\n "generation_name": "ishaan-generation-langchain-client",\n "generation_id": "langchain-client-gen-id22",\n "trace_id": "langchain-client-trace-id22",\n "trace_user_id": "langchain-client-user-id2"\n }\n }\n)\n\nmessages = [\n SystemMessage(\n content="You are a helpful assistant that im using to make a test request to."\n ),\n HumanMessage(\n content="test from litellm. tell me why it\'s amazing in 1 sentence"\n ),\n]\nresponse = chat(messages)\n\nprint(response)\n\n '})})]})]})})]})]})})})})},es=n(33509),el=n(30569);let{Sider:er}=es.default;var ea=e=>{let{setPage:t}=e;return(0,s.jsx)(es.default,{style:{minHeight:"100vh",maxWidth:"120px"},children:(0,s.jsx)(er,{width:120,children:(0,s.jsxs)(el.Z,{mode:"inline",defaultSelectedKeys:["1"],style:{height:"100%",borderRight:0},children:[(0,s.jsx)(el.Z.Item,{onClick:()=>t("api-keys"),children:"API Keys"},"1"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("models"),children:"Models"},"2"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("llm-playground"),children:"Chat UI"},"3"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("usage"),children:"Usage"},"4")]})})})};let eo=e=>{let{payload:t,active:n}=e;if(!n||!t)return null;let l=t[0].payload,r=l.startTime,a=Object.entries(l.models).map(e=>{let[t,n]=e;return[t,n]});a.sort((e,t)=>t[1]-e[1]);let o=a.slice(0,5);return(0,s.jsxs)("div",{className:"w-56 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown",children:[r,o.map(e=>{let[t,n]=e;return(0,s.jsx)("div",{className:"flex flex-1 space-x-10",children:(0,s.jsx)("div",{className:"p-2",children:(0,s.jsxs)("p",{className:"text-tremor-content text-xs",children:[t,":",(0,s.jsxs)("span",{className:"text-xs text-tremor-content-emphasis",children:[" ",n?n<.01?"<$0.01":n.toFixed(2):""]})]})})},t)})]})};var ei=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,o=new Date,[i,c]=(0,l.useState)([]),[d,m]=(0,l.useState)([]),[h,u]=(0,l.useState)([]),x=new Date(o.getFullYear(),o.getMonth(),1),g=new Date(o.getFullYear(),o.getMonth()+1,0),Z=k(x),w=k(g);function k(e){let t=e.getFullYear(),n=e.getMonth()+1,s=e.getDate();return"".concat(t,"-").concat(n<10?"0"+n:n,"-").concat(s<10?"0"+s:s)}return console.log("Start date is ".concat(Z)),console.log("End date is ".concat(w)),(0,l.useEffect)(()=>{t&&n&&r&&a&&(async()=>{try{await p(t,n,r,a,Z,w).then(async e=>{let n=(await j(t,function(e){let t=[];e.forEach(e=>{Object.entries(e).forEach(e=>{let[n,s]=e;"spend"!==n&&"startTime"!==n&&"models"!==n&&"users"!==n&&t.push({key:n,spend:s})})}),t.sort((e,t)=>Number(t.spend)-Number(e.spend));let n=t.slice(0,5).map(e=>e.key);return console.log("topKeys: ".concat(Object.keys(n[0]))),n}(e))).info.map(e=>({key:(e.key_name||e.key_alias||e.token).substring(0,7),spend:e.spend}));m(n),u(function(e){let t={};e.forEach(e=>{Object.entries(e.users).forEach(e=>{let[n,s]=e;""!==n&&null!=n&&"None"!=n&&(t[n]||(t[n]=0),t[n]+=s)})});let n=Object.entries(t).map(e=>{let[t,n]=e;return{user_id:t,spend:n}});n.sort((e,t)=>t.spend-e.spend);let s=n.slice(0,5);return console.log("topKeys: ".concat(Object.values(s[0]))),s}(e)),c(e)})}catch(e){console.error("There was an error fetching the data",e)}})()},[t,n,r,a,Z,w]),(0,s.jsx)("div",{style:{width:"100%"},children:(0,s.jsxs)(f.Z,{numItems:2,className:"gap-2 p-10 h-[75vh] w-full",children:[(0,s.jsx)(y.Z,{numColSpan:2,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Monthly Spend"}),(0,s.jsx)(F.Z,{data:i,index:"startTime",categories:["spend"],colors:["blue"],valueFormatter:e=>"$ ".concat(new Intl.NumberFormat("us").format(e).toString()),yAxisWidth:100,tickGap:5,customTooltip:eo})]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Top API Keys"}),(0,s.jsx)(F.Z,{className:"mt-4 h-40",data:d,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:80,tickGap:5,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Top Users"}),(0,s.jsx)(F.Z,{className:"mt-4 h-40",data:h,index:"user_id",categories:["spend"],colors:["blue"],yAxisWidth:200,layout:"vertical",showXAxis:!1,showLegend:!1})]})})]})})},ec=()=>{let[e,t]=(0,l.useState)(null),[n,a]=(0,l.useState)(null),o=(0,r.useSearchParams)(),c=o.get("userID"),d=o.get("token"),[m,h]=(0,l.useState)("api-keys"),[u,x]=(0,l.useState)(null);return(0,l.useEffect)(()=>{if(d){let e=(0,q.o)(d);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),x(e.key),e.user_role){let n=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":return"Admin";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",n),t(n)}else console.log("User role not defined");e.user_email?a(e.user_email):console.log("User Email is not set ".concat(e))}}},[d]),(0,s.jsx)(l.Suspense,{fallback:(0,s.jsx)("div",{children:"Loading..."}),children:(0,s.jsxs)("div",{className:"flex flex-col min-h-screen",children:[(0,s.jsx)(i,{userID:c,userRole:e,userEmail:n}),(0,s.jsxs)("div",{className:"flex flex-1 overflow-auto",children:[(0,s.jsx)(ea,{setPage:h}),"api-keys"==m?(0,s.jsx)(G,{userID:c,userRole:e,setUserRole:t,userEmail:n,setUserEmail:a}):"models"==m?(0,s.jsx)($,{userID:c,userRole:e,token:d,accessToken:u}):"llm-playground"==m?(0,s.jsx)(en,{userID:c,userRole:e,token:d,accessToken:u}):(0,s.jsx)(ei,{userID:c,userRole:e,token:d,accessToken:u})]})]})})}}},function(e){e.O(0,[145,971,69,744],function(){return e(e.s=20661)}),_N_E=e.O()}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{20661:function(e,t,n){Promise.resolve().then(n.bind(n,48016))},48016:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return ec}});var s=n(3827),l=n(64090),r=n(47907),a=n(8792),o=n(2179),i=e=>{let{userID:t,userRole:n,userEmail:l}=e;return console.log("User ID:",t),console.log("userEmail:",l),(0,s.jsxs)("nav",{className:"left-0 right-0 top-0 flex justify-between items-center h-12 mb-4",children:[(0,s.jsx)("div",{className:"text-left mx-4 my-2 absolute top-0 left-0",children:(0,s.jsx)("div",{className:"flex flex-col items-center",children:(0,s.jsx)(a.default,{href:"/",children:(0,s.jsx)("button",{className:"text-gray-800 text-2xl px-4 py-1 rounded text-center",children:"\uD83D\uDE85 LiteLLM"})})})}),(0,s.jsx)("div",{className:"text-right mx-4 my-2 absolute top-0 right-0",children:(0,s.jsxs)(o.Z,{variant:"secondary",children:[l,(0,s.jsxs)("p",{children:["Role: ",n]}),(0,s.jsxs)("p",{children:["ID: ",t]})]})})]})},c=n(80588);let d=async(e,t,n)=>{try{if(console.log("Form Values in keyCreateCall:",n),n.description&&(n.metadata||(n.metadata={}),n.metadata.description=n.description,delete n.description,n.metadata=JSON.stringify(n.metadata)),n.metadata){console.log("formValues.metadata:",n.metadata);try{n.metadata=JSON.parse(n.metadata)}catch(e){throw c.ZP.error("Failed to parse metadata: "+e),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",n);let s=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:t,...n})});if(!s.ok){let e=await s.text();throw c.ZP.error("Failed to create key: "+e),console.error("Error response from the server:",e),Error("Network response was not ok")}let l=await s.json();return console.log("API Response:",l),l}catch(e){throw console.error("Failed to create key:",e),e}},m=async(e,t)=>{try{console.log("in keyDeleteCall:",t),c.ZP.info("Making key delete request");let n=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[t]})});if(!n.ok){let e=await n.text();throw c.ZP.error("Failed to delete key: "+e),Error("Network response was not ok")}let s=await n.json();return console.log(s),c.ZP.success("API Key Deleted"),s}catch(e){throw console.error("Failed to create key:",e),e}},h=async(e,t,n)=>{try{let s="/user/info";"App Owner"==n&&(s="".concat(s,"/?user_id=").concat(t)),c.ZP.info("Requesting user data");let l=await fetch(s,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw c.ZP.error(e),Error("Network response was not ok")}let r=await l.json();return c.ZP.info("Received user data"),r}catch(e){throw console.error("Failed to create key:",e),e}},u=async(e,t,n)=>{try{c.ZP.info("Requesting model data");let t=await fetch("/model/info",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw c.ZP.error(e),Error("Network response was not ok")}let n=await t.json();return c.ZP.info("Received model data"),n}catch(e){throw console.error("Failed to create key:",e),e}},x=async(e,t)=>{try{let n="/spend/logs";console.log("in keySpendLogsCall:",n);let s=await fetch("".concat(n,"/?api_key=").concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw c.ZP.error(e),Error("Network response was not ok")}let l=await s.json();return console.log(l),l}catch(e){throw console.error("Failed to create key:",e),e}},p=async(e,t,n,s,l,r)=>{try{let t="/spend/logs";t="App Owner"==n?"".concat(t,"/?user_id=").concat(s,"&start_date=").concat(l,"&end_date=").concat(r):"".concat(t,"/?start_date=").concat(l,"&end_date=").concat(r),c.ZP.info("Making spend logs request");let a=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!a.ok){let e=await a.text();throw c.ZP.error(e),Error("Network response was not ok")}let o=await a.json();return console.log(o),c.ZP.success("Spend Logs received"),o}catch(e){throw console.error("Failed to create key:",e),e}},j=async(e,t)=>{try{let n=await fetch("/key/info",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:t})});if(!n.ok){let e=await n.text();throw c.ZP.error(e),Error("Network response was not ok")}let s=await n.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},g=async(e,t)=>{try{let n="/spend/users";console.log("in spendUsersCall:",n);let s=await fetch("".concat(n,"/?user_id=").concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw c.ZP.error(e),Error("Network response was not ok")}let l=await s.json();return console.log(l),l}catch(e){throw console.error("Failed to get spend for user",e),e}};var y=n(10384),f=n(46453),Z=n(71801),w=n(13969),k=n(12143),_=n(77171),v=n(29714),b=n(88707),S=n(1861);let{Option:N}=w.default;var I=e=>{let{userID:t,userRole:n,accessToken:r,data:a,userModels:i,setData:m}=e,[h]=k.Z.useForm(),[u,x]=(0,l.useState)(!1),[p,j]=(0,l.useState)(null),g=()=>{x(!1),h.resetFields()},I=()=>{x(!1),j(null),h.resetFields()},A=async e=>{try{c.ZP.info("Making API Call"),x(!0);let n=await d(r,t,e);m(e=>e?[...e,n]:[n]),j(n.key),c.ZP.success("API Key Created"),h.resetFields(),localStorage.removeItem("userData"+t)}catch(e){console.error("Error creating the key:",e)}};return(0,s.jsxs)("div",{children:[(0,s.jsx)(o.Z,{className:"mx-auto",onClick:()=>x(!0),children:"+ Create New Key"}),(0,s.jsx)(_.Z,{title:"Create Key",visible:u,width:800,footer:null,onOk:g,onCancel:I,children:(0,s.jsxs)(k.Z,{form:h,onFinish:A,labelCol:{span:6},wrapperCol:{span:16},labelAlign:"left",children:["App Owner"===n||"Admin"===n?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(k.Z.Item,{label:"Key Name",name:"key_alias",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Team ID",name:"team_id",children:(0,s.jsx)(v.Z,{placeholder:"ai_team"})}),(0,s.jsx)(k.Z.Item,{label:"Models",name:"models",children:(0,s.jsx)(w.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:i.map(e=>(0,s.jsx)(N,{value:e,children:e},e))})}),(0,s.jsx)(k.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,s.jsx)(b.Z,{step:.01,precision:2,width:200})}),(0,s.jsx)(k.Z.Item,{label:"Duration (eg: 30s, 30h, 30d)",name:"duration",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Metadata",name:"metadata",children:(0,s.jsx)(v.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})})]}):(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(k.Z.Item,{label:"Key Name",name:"key_alias",children:(0,s.jsx)(v.Z,{})}),(0,s.jsx)(k.Z.Item,{label:"Team ID (Contact Group)",name:"team_id",children:(0,s.jsx)(v.Z,{placeholder:"ai_team"})}),(0,s.jsx)(k.Z.Item,{label:"Description",name:"description",children:(0,s.jsx)(v.Z.TextArea,{placeholder:"Enter description",rows:4})})]}),(0,s.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,s.jsx)(S.ZP,{htmlType:"submit",children:"Create Key"})})]})}),p&&(0,s.jsx)(_.Z,{title:"Save your key",visible:u,onOk:g,onCancel:I,footer:null,children:(0,s.jsxs)(f.Z,{numItems:1,className:"gap-2 w-full",children:[(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons, ",(0,s.jsx)("b",{children:"you will not be able to view it again"})," ","through your LiteLLM account. If you lose this secret key, you will need to generate a new one."]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:null!=p?(0,s.jsxs)(Z.Z,{children:["API Key: ",p]}):(0,s.jsx)(Z.Z,{children:"Key being created, this might take 30s"})})]})})]})},A=n(33393),C=n(13810),D=n(61244),T=n(10827),P=n(3851),E=n(2044),O=n(64167),R=n(74480),M=n(7178),U=n(42440),F=n(9853),K=n(67989),L=n(56863),z=e=>{let{token:t,accessToken:n,keySpend:r,keyBudget:a,keyName:i}=e,[c,d]=(0,l.useState)(!1),[m,h]=(0,l.useState)(null),[u,p]=(0,l.useState)(null),j=async()=>{try{if(null==n||null==t)return;console.log("accessToken: ".concat(n,"; token: ").concat(t));let e=await x(n,t);console.log("Response:",e);let s=Object.values(e).reduce((e,t)=>{let n=new Date(t.startTime),s=new Intl.DateTimeFormat("en-US",{day:"2-digit",month:"short"}).format(n);return e[s]=(e[s]||0)+t.spend,e},{}),l=Object.entries(s);l.sort((e,t)=>{let[n]=e,[s]=t,l=new Date(n),r=new Date(s);return l.getTime()-r.getTime()});let r=Object.fromEntries(l);console.log(r);let a=Object.values(e).reduce((e,t)=>{let n=t.user;return e[n]=(e[n]||0)+t.spend,e},{});console.log(s),console.log(a);let o=[];for(let[e,t]of Object.entries(r))o.push({day:e,spend:t});let i=Object.entries(a).sort((e,t)=>t[1]-e[1]).slice(0,5).map(e=>{let[t,n]=e;return{name:t,value:n}});h(o),p(i),console.log("arrayBarChart:",o)}catch(e){console.error("There was an error fetching the data",e)}};return t?(0,s.jsxs)("div",{children:[(0,s.jsx)(o.Z,{className:"mx-auto",onClick:()=>{console.log("Show Modal triggered"),d(!0),j()},children:"View Spend Report"}),(0,s.jsxs)(_.Z,{visible:c,width:1e3,onOk:()=>{d(!1)},onCancel:()=>{d(!1)},footer:null,children:[(0,s.jsxs)(U.Z,{style:{textAlign:"left"},children:["Key Name: ",i]}),(0,s.jsxs)(L.Z,{children:["Monthly Spend $",r]}),(0,s.jsx)(C.Z,{className:"mt-6 mb-6",children:m&&(0,s.jsx)(F.Z,{className:"mt-6",data:m,colors:["green"],index:"day",categories:["spend"],yAxisWidth:48})}),(0,s.jsx)(U.Z,{className:"mt-6",children:"Top 5 Users Spend (USD)"}),(0,s.jsx)(C.Z,{className:"mb-6",children:u&&(0,s.jsx)(K.Z,{className:"mt-6",data:u,color:"teal"})})]})]}):null},B=e=>{let{userID:t,accessToken:n,data:r,setData:a}=e,[i,c]=(0,l.useState)(!1),[d,h]=(0,l.useState)(!1),[u,x]=(0,l.useState)(null),p=async e=>{null!=r&&(x(e),localStorage.removeItem("userData"+t),h(!0))},j=async()=>{if(null!=u&&null!=r){try{await m(n,u);let e=r.filter(e=>e.token!==u);a(e)}catch(e){console.error("Error deleting the key:",e)}h(!1),x(null)}};if(null!=r)return console.log("RERENDER TRIGGERED"),(0,s.jsxs)(C.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4",children:[(0,s.jsx)(U.Z,{children:"API Keys"}),(0,s.jsxs)(T.Z,{className:"mt-5",children:[(0,s.jsx)(O.Z,{children:(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(R.Z,{children:"Key Alias"}),(0,s.jsx)(R.Z,{children:"Secret Key"}),(0,s.jsx)(R.Z,{children:"Spend (USD)"}),(0,s.jsx)(R.Z,{children:"Key Budget (USD)"}),(0,s.jsx)(R.Z,{children:"Team ID"}),(0,s.jsx)(R.Z,{children:"Metadata"}),(0,s.jsx)(R.Z,{children:"Models"}),(0,s.jsx)(R.Z,{children:"TPM / RPM Limits"}),(0,s.jsx)(R.Z,{children:"Expires"})]})}),(0,s.jsx)(P.Z,{children:r.map(e=>(console.log(e),"litellm-dashboard"===e.team_id)?null:(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(E.Z,{children:null!=e.key_alias?(0,s.jsx)(Z.Z,{children:e.key_alias}):(0,s.jsx)(Z.Z,{children:"Not Set"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.key_name})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.spend})}),(0,s.jsx)(E.Z,{children:null!=e.max_budget?(0,s.jsx)(Z.Z,{children:e.max_budget}):(0,s.jsx)(Z.Z,{children:"Unlimited Budget"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:e.team_id})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:JSON.stringify(e.metadata)})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(Z.Z,{children:JSON.stringify(e.models)})}),(0,s.jsx)(E.Z,{children:(0,s.jsxs)(Z.Z,{children:["TPM Limit: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,s.jsx)("br",{})," RPM Limit:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,s.jsx)(E.Z,{children:null!=e.expires?(0,s.jsx)(Z.Z,{children:e.expires}):(0,s.jsx)(Z.Z,{children:"Never expires"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(D.Z,{onClick:()=>p(e.token),icon:A.Z,size:"sm"})}),(0,s.jsx)(E.Z,{children:(0,s.jsx)(z,{token:e.token,accessToken:n,keySpend:e.spend,keyBudget:e.max_budget,keyName:e.key_name})})]},e.token))})]}),d&&(0,s.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,s.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,s.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,s.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,s.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,s.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,s.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,s.jsx)("div",{className:"sm:flex sm:items-start",children:(0,s.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,s.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Key"}),(0,s.jsx)("div",{className:"mt-2",children:(0,s.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this key ?"})})]})})}),(0,s.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,s.jsx)(o.Z,{onClick:j,color:"red",className:"ml-2",children:"Delete"}),(0,s.jsx)(o.Z,{onClick:()=>{h(!1),x(null)},children:"Cancel"})]})]})]})})]})},J=e=>{let{userID:t,userSpendData:n,userRole:r,accessToken:a}=e;console.log("User SpendData:",n);let[o,i]=(0,l.useState)(null==n?void 0:n.spend),[c,d]=(0,l.useState)((null==n?void 0:n.max_budget)||null);return(0,l.useEffect)(()=>{(async()=>{if("Admin"===r)try{let e=await g(a,"litellm-proxy-budget");console.log("Result from callSpendUsers:",e);let t=e[0];i(null==t?void 0:t.spend),d((null==t?void 0:t.max_budget)||null)}catch(e){console.error("Failed to get spend for user",e)}})()},[r,a,t]),(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)(C.Z,{className:"mx-auto mb-4",children:[(0,s.jsxs)(L.Z,{children:["$",o]}),(0,s.jsxs)(U.Z,{children:["/ ",null!==c?"$".concat(c," limit"):"No limit"]})]})})},q=n(37963);console.log("isLocal:",!1);var G=e=>{let{userID:t,userRole:n,setUserRole:a,userEmail:o,setUserEmail:i}=e,[c,d]=(0,l.useState)(null),[m,x]=(0,l.useState)(null),p=(0,r.useSearchParams)();p.get("viewSpend"),(0,r.useRouter)();let j=p.get("token"),[g,Z]=(0,l.useState)(null),[w,k]=(0,l.useState)([]);if((0,l.useEffect)(()=>{if(j){let e=(0,q.o)(j);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),Z(e.key),e.user_role){let t=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":return"Admin";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",t),a(t)}else console.log("User role not defined");e.user_email?i(e.user_email):console.log("User Email is not set ".concat(e))}}if(t&&g&&n&&!c){let e=localStorage.getItem("userData"+t),s=localStorage.getItem("userSpendData"+t),l=localStorage.getItem("userModels"+t);e&&s&&l?(d(JSON.parse(e)),x(JSON.parse(s)),k(JSON.parse(l))):(async()=>{try{let e=await h(g,t,n);x(e.user_info),d(e.keys),localStorage.setItem("userData"+t,JSON.stringify(e.keys)),localStorage.setItem("userSpendData"+t,JSON.stringify(e.user_info));let s=await u(g,t,n);console.log("model_info:",s);let l=s.data.map(e=>e.model_name);console.log("available_model_names:",l),k(l),console.log("userModels:",w),localStorage.setItem("userModels"+t,JSON.stringify(l))}catch(e){console.error("There was an error fetching the data",e)}})()}},[t,j,g,c,n]),null==t||null==j){let e="/sso/key/generate";return console.log("Full URL:",e),window.location.href=e,null}return null==g?null:(null==n&&a("App Owner"),(0,s.jsx)("div",{children:(0,s.jsx)(f.Z,{numItems:1,className:"gap-0 p-10 h-[75vh] w-full",children:(0,s.jsxs)(y.Z,{numColSpan:1,children:[(0,s.jsx)(J,{userID:t,userSpendData:m,userRole:n,accessToken:g}),(0,s.jsx)(B,{userID:t,accessToken:g,data:c,setData:d}),(0,s.jsx)(I,{userID:t,userRole:n,userModels:w,accessToken:g,data:c,setData:d})]})})}))},$=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,[o,i]=(0,l.useState)({data:[]});if((0,l.useEffect)(()=>{if(!t||!n||!r||!a)return;let e=async()=>{try{let e=await u(t,a,r);console.log("Model data response:",e.data),i(e)}catch(e){console.error("There was an error fetching the model data",e)}};t&&n&&r&&a&&e()},[t,n,r,a]),!o)return(0,s.jsx)("div",{children:"Loading..."});for(let e=0;e(0,s.jsxs)(M.Z,{children:[(0,s.jsx)(E.Z,{children:(0,s.jsx)(U.Z,{children:e.model_name})}),(0,s.jsx)(E.Z,{children:e.provider}),(0,s.jsx)(E.Z,{children:e.input_cost}),(0,s.jsx)(E.Z,{children:e.output_cost}),(0,s.jsx)(E.Z,{children:e.max_tokens})]},e.model_name))})]})})})})},V=n(92836),W=n(26734),H=n(41608),Y=n(32126),X=n(23682),Q=n(12968),ee=n(67951);async function et(e,t,n,s){console.log("isLocal:",!1);let l=window.location.origin,r=new Q.ZP.OpenAI({apiKey:s,baseURL:l,dangerouslyAllowBrowser:!0});for await(let s of(await r.chat.completions.create({model:n,stream:!0,messages:[{role:"user",content:e}]})))console.log(s),s.choices[0].delta.content&&t(s.choices[0].delta.content)}var en=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,[o,i]=(0,l.useState)(""),[c,d]=(0,l.useState)([]),[m,h]=(0,l.useState)(void 0),[x,p]=(0,l.useState)(null);(0,l.useEffect)(()=>{t&&n&&r&&a&&(async()=>{let e=await u(t,a,r);console.log("model_info:",e),(null==e?void 0:e.data.length)>0&&(p(e),h(e.data[0].model_name))})()},[t,a,r]);let j=(e,t)=>{d(n=>{let s=n[n.length-1];return s&&s.role===e?[...n.slice(0,n.length-1),{role:e,content:s.content+t}]:[...n,{role:e,content:t}]})},g=async()=>{if(""!==o.trim()&&t&&n&&r&&a){d(e=>[...e,{role:"user",content:o}]);try{m&&await et(o,e=>j("assistant",e),m,t)}catch(e){console.error("Error fetching model response",e),j("assistant","Error fetching model response")}i("")}};return(0,s.jsx)("div",{style:{width:"100%",position:"relative"},children:(0,s.jsx)(f.Z,{className:"gap-2 p-10 h-[75vh] w-full",children:(0,s.jsx)(C.Z,{children:(0,s.jsxs)(W.Z,{children:[(0,s.jsxs)(H.Z,{className:"mt-4",children:[(0,s.jsx)(V.Z,{children:"Chat"}),(0,s.jsx)(V.Z,{children:"API Reference"})]}),(0,s.jsxs)(X.Z,{children:[(0,s.jsxs)(Y.Z,{children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("label",{children:"Select Model:"}),(0,s.jsx)("select",{value:m||"",onChange:e=>h(e.target.value),children:null==x?void 0:x.data.map(e=>(0,s.jsx)("option",{value:e.model_name,children:e.model_name},e.model_name))})]}),(0,s.jsxs)(T.Z,{className:"mt-5",style:{display:"block",maxHeight:"60vh",overflowY:"auto"},children:[(0,s.jsx)(O.Z,{children:(0,s.jsx)(M.Z,{children:(0,s.jsx)(E.Z,{children:(0,s.jsx)(U.Z,{children:"Chat"})})})}),(0,s.jsx)(P.Z,{children:c.map((e,t)=>(0,s.jsx)(M.Z,{children:(0,s.jsx)(E.Z,{children:"".concat(e.role,": ").concat(e.content)})},t))})]}),(0,s.jsx)("div",{className:"mt-3",style:{position:"absolute",bottom:5,width:"95%"},children:(0,s.jsxs)("div",{className:"flex",children:[(0,s.jsx)("input",{type:"text",value:o,onChange:e=>i(e.target.value),className:"flex-1 p-2 border rounded-md mr-2",placeholder:"Type your message..."}),(0,s.jsx)("button",{onClick:g,className:"p-2 bg-blue-500 text-white rounded-md",children:"Send"})]})})]}),(0,s.jsx)(Y.Z,{children:(0,s.jsxs)(W.Z,{children:[(0,s.jsxs)(H.Z,{children:[(0,s.jsx)(V.Z,{children:"OpenAI Python SDK"}),(0,s.jsx)(V.Z,{children:"LlamaIndex"}),(0,s.jsx)(V.Z,{children:"Langchain Py"})]}),(0,s.jsxs)(X.Z,{children:[(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nimport openai\nclient = openai.OpenAI(\n api_key="your_api_key",\n base_url="http://0.0.0.0:4000" # proxy base url\n)\n\nresponse = client.chat.completions.create(\n model="gpt-3.5-turbo", # model to use from Models Tab\n messages = [\n {\n "role": "user",\n "content": "this is a test request, write a short poem"\n }\n ],\n extra_body={\n "metadata": {\n "generation_name": "ishaan-generation-openai-client",\n "generation_id": "openai-client-gen-id22",\n "trace_id": "openai-client-trace-id22",\n "trace_user_id": "openai-client-user-id2"\n }\n }\n)\n\nprint(response)\n '})}),(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nimport os, dotenv\n\nfrom llama_index.llms import AzureOpenAI\nfrom llama_index.embeddings import AzureOpenAIEmbedding\nfrom llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\n\nllm = AzureOpenAI(\n engine="azure-gpt-3.5", # model_name on litellm proxy\n temperature=0.0,\n azure_endpoint="http://0.0.0.0:4000", # litellm proxy endpoint\n api_key="sk-1234", # litellm proxy API Key\n api_version="2023-07-01-preview",\n)\n\nembed_model = AzureOpenAIEmbedding(\n deployment_name="azure-embedding-model",\n azure_endpoint="http://0.0.0.0:4000",\n api_key="sk-1234",\n api_version="2023-07-01-preview",\n)\n\n\ndocuments = SimpleDirectoryReader("llama_index_data").load_data()\nservice_context = ServiceContext.from_defaults(llm=llm, embed_model=embed_model)\nindex = VectorStoreIndex.from_documents(documents, service_context=service_context)\n\nquery_engine = index.as_query_engine()\nresponse = query_engine.query("What did the author do growing up?")\nprint(response)\n\n '})}),(0,s.jsx)(Y.Z,{children:(0,s.jsx)(ee.Z,{language:"python",children:'\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.prompts.chat import (\n ChatPromptTemplate,\n HumanMessagePromptTemplate,\n SystemMessagePromptTemplate,\n)\nfrom langchain.schema import HumanMessage, SystemMessage\n\nchat = ChatOpenAI(\n openai_api_base="http://0.0.0.0:8000",\n model = "gpt-3.5-turbo",\n temperature=0.1,\n extra_body={\n "metadata": {\n "generation_name": "ishaan-generation-langchain-client",\n "generation_id": "langchain-client-gen-id22",\n "trace_id": "langchain-client-trace-id22",\n "trace_user_id": "langchain-client-user-id2"\n }\n }\n)\n\nmessages = [\n SystemMessage(\n content="You are a helpful assistant that im using to make a test request to."\n ),\n HumanMessage(\n content="test from litellm. tell me why it\'s amazing in 1 sentence"\n ),\n]\nresponse = chat(messages)\n\nprint(response)\n\n '})})]})]})})]})]})})})})},es=n(33509),el=n(30569);let{Sider:er}=es.default;var ea=e=>{let{setPage:t}=e;return(0,s.jsx)(es.default,{style:{minHeight:"100vh",maxWidth:"120px"},children:(0,s.jsx)(er,{width:120,children:(0,s.jsxs)(el.Z,{mode:"inline",defaultSelectedKeys:["1"],style:{height:"100%",borderRight:0},children:[(0,s.jsx)(el.Z.Item,{onClick:()=>t("api-keys"),children:"API Keys"},"1"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("models"),children:"Models"},"2"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("llm-playground"),children:"Chat UI"},"3"),(0,s.jsx)(el.Z.Item,{onClick:()=>t("usage"),children:"Usage"},"4")]})})})};let eo=e=>{let{payload:t,active:n}=e;if(!n||!t)return null;let l=t[0].payload,r=l.startTime,a=Object.entries(l.models).map(e=>{let[t,n]=e;return[t,n]});a.sort((e,t)=>t[1]-e[1]);let o=a.slice(0,5);return(0,s.jsxs)("div",{className:"w-56 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown",children:[r,o.map(e=>{let[t,n]=e;return(0,s.jsx)("div",{className:"flex flex-1 space-x-10",children:(0,s.jsx)("div",{className:"p-2",children:(0,s.jsxs)("p",{className:"text-tremor-content text-xs",children:[t,":",(0,s.jsxs)("span",{className:"text-xs text-tremor-content-emphasis",children:[" ",n?n<.01?"<$0.01":n.toFixed(2):""]})]})})},t)})]})};var ei=e=>{let{accessToken:t,token:n,userRole:r,userID:a}=e,o=new Date,[i,c]=(0,l.useState)([]),[d,m]=(0,l.useState)([]),[h,u]=(0,l.useState)([]),x=new Date(o.getFullYear(),o.getMonth(),1),g=new Date(o.getFullYear(),o.getMonth()+1,0),Z=k(x),w=k(g);function k(e){let t=e.getFullYear(),n=e.getMonth()+1,s=e.getDate();return"".concat(t,"-").concat(n<10?"0"+n:n,"-").concat(s<10?"0"+s:s)}return console.log("Start date is ".concat(Z)),console.log("End date is ".concat(w)),(0,l.useEffect)(()=>{t&&n&&r&&a&&(async()=>{try{await p(t,n,r,a,Z,w).then(async e=>{let n=(await j(t,function(e){let t=[];e.forEach(e=>{Object.entries(e).forEach(e=>{let[n,s]=e;"spend"!==n&&"startTime"!==n&&"models"!==n&&"users"!==n&&t.push({key:n,spend:s})})}),t.sort((e,t)=>Number(t.spend)-Number(e.spend));let n=t.slice(0,5).map(e=>e.key);return console.log("topKeys: ".concat(Object.keys(n[0]))),n}(e))).info.map(e=>({key:(e.key_name||e.key_alias||e.token).substring(0,7),spend:e.spend}));m(n),u(function(e){let t={};e.forEach(e=>{Object.entries(e.users).forEach(e=>{let[n,s]=e;""!==n&&null!=n&&"None"!=n&&(t[n]||(t[n]=0),t[n]+=s)})});let n=Object.entries(t).map(e=>{let[t,n]=e;return{user_id:t,spend:n}});n.sort((e,t)=>t.spend-e.spend);let s=n.slice(0,5);return console.log("topKeys: ".concat(Object.values(s[0]))),s}(e)),c(e)})}catch(e){console.error("There was an error fetching the data",e)}})()},[t,n,r,a,Z,w]),(0,s.jsx)("div",{style:{width:"100%"},children:(0,s.jsxs)(f.Z,{numItems:2,className:"gap-2 p-10 h-[75vh] w-full",children:[(0,s.jsx)(y.Z,{numColSpan:2,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Monthly Spend"}),(0,s.jsx)(F.Z,{data:i,index:"startTime",categories:["spend"],colors:["blue"],valueFormatter:e=>"$ ".concat(new Intl.NumberFormat("us").format(e).toString()),yAxisWidth:100,tickGap:5,customTooltip:eo})]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Top API Keys"}),(0,s.jsx)(F.Z,{className:"mt-4 h-40",data:d,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:80,tickGap:5,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,s.jsx)(y.Z,{numColSpan:1,children:(0,s.jsxs)(C.Z,{children:[(0,s.jsx)(U.Z,{children:"Top Users"}),(0,s.jsx)(F.Z,{className:"mt-4 h-40",data:h,index:"user_id",categories:["spend"],colors:["blue"],yAxisWidth:200,layout:"vertical",showXAxis:!1,showLegend:!1})]})})]})})},ec=()=>{let[e,t]=(0,l.useState)(null),[n,a]=(0,l.useState)(null),o=(0,r.useSearchParams)(),c=o.get("userID"),d=o.get("token"),[m,h]=(0,l.useState)("api-keys"),[u,x]=(0,l.useState)(null);return(0,l.useEffect)(()=>{if(d){let e=(0,q.o)(d);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),x(e.key),e.user_role){let n=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":return"Admin";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",n),t(n)}else console.log("User role not defined");e.user_email?a(e.user_email):console.log("User Email is not set ".concat(e))}}},[d]),(0,s.jsx)(l.Suspense,{fallback:(0,s.jsx)("div",{children:"Loading..."}),children:(0,s.jsxs)("div",{className:"flex flex-col min-h-screen",children:[(0,s.jsx)(i,{userID:c,userRole:e,userEmail:n}),(0,s.jsxs)("div",{className:"flex flex-1 overflow-auto",children:[(0,s.jsx)(ea,{setPage:h}),"api-keys"==m?(0,s.jsx)(G,{userID:c,userRole:e,setUserRole:t,userEmail:n,setUserEmail:a}):"models"==m?(0,s.jsx)($,{userID:c,userRole:e,token:d,accessToken:u}):"llm-playground"==m?(0,s.jsx)(en,{userID:c,userRole:e,token:d,accessToken:u}):(0,s.jsx)(ei,{userID:c,userRole:e,token:d,accessToken:u})]})]})})}}},function(e){e.O(0,[145,971,69,744],function(){return e(e.s=20661)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/ui/litellm-dashboard/out/_next/static/lLFQRQnIrRo-GJf5spHEd/_buildManifest.js b/ui/litellm-dashboard/out/_next/static/unBuvDqydg0yodtP5c3nQ/_buildManifest.js similarity index 100% rename from ui/litellm-dashboard/out/_next/static/lLFQRQnIrRo-GJf5spHEd/_buildManifest.js rename to ui/litellm-dashboard/out/_next/static/unBuvDqydg0yodtP5c3nQ/_buildManifest.js diff --git a/ui/litellm-dashboard/out/_next/static/lLFQRQnIrRo-GJf5spHEd/_ssgManifest.js b/ui/litellm-dashboard/out/_next/static/unBuvDqydg0yodtP5c3nQ/_ssgManifest.js similarity index 100% rename from ui/litellm-dashboard/out/_next/static/lLFQRQnIrRo-GJf5spHEd/_ssgManifest.js rename to ui/litellm-dashboard/out/_next/static/unBuvDqydg0yodtP5c3nQ/_ssgManifest.js diff --git a/ui/litellm-dashboard/out/index.html b/ui/litellm-dashboard/out/index.html index f54a24355..80296f4f6 100644 --- a/ui/litellm-dashboard/out/index.html +++ b/ui/litellm-dashboard/out/index.html @@ -1 +1 @@ -🚅 LiteLLM \ No newline at end of file +🚅 LiteLLM \ No newline at end of file diff --git a/ui/litellm-dashboard/out/index.txt b/ui/litellm-dashboard/out/index.txt index d0cebc66f..b6bb2c868 100644 --- a/ui/litellm-dashboard/out/index.txt +++ b/ui/litellm-dashboard/out/index.txt @@ -1,7 +1,7 @@ 2:I[77831,[],""] -3:I[48016,["145","static/chunks/145-9c160ad5539e000f.js","931","static/chunks/app/page-fcb69349f15d154b.js"],""] +3:I[48016,["145","static/chunks/145-9c160ad5539e000f.js","931","static/chunks/app/page-7bb820bd6902dbf2.js"],""] 4:I[5613,[],""] 5:I[31778,[],""] -0:["lLFQRQnIrRo-GJf5spHEd",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/c18941d97fb7245b.css","precedence":"next","crossOrigin":""}]],"$L6"]]]] +0:["unBuvDqydg0yodtP5c3nQ",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/c18941d97fb7245b.css","precedence":"next","crossOrigin":""}]],"$L6"]]]] 6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"🚅 LiteLLM"}],["$","meta","3",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","4",{"rel":"icon","href":"/ui/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]] 1:null diff --git a/ui/litellm-dashboard/src/components/chat_ui.tsx b/ui/litellm-dashboard/src/components/chat_ui.tsx index fe1f4105e..edab67b2b 100644 --- a/ui/litellm-dashboard/src/components/chat_ui.tsx +++ b/ui/litellm-dashboard/src/components/chat_ui.tsx @@ -21,9 +21,13 @@ interface ChatUIProps { } async function generateModelResponse(inputMessage: string, updateUI: (chunk: string) => void, selectedModel: string, accessToken: string) { - const client = new openai.OpenAI({ + // base url should be the current base_url + const isLocal = process.env.NODE_ENV === "development"; + console.log("isLocal:", isLocal); + const proxyBaseUrl = isLocal ? "http://localhost:4000" : window.location.origin; + const client = new openai.OpenAI({ apiKey: accessToken, // Replace with your OpenAI API key - baseURL: 'http://0.0.0.0:4000', // Replace with your OpenAI API base URL + baseURL: proxyBaseUrl, // Replace with your OpenAI API base URL dangerouslyAllowBrowser: true, // using a temporary litellm proxy key });