From 0e34d631537ba67e17bff5bd228ccc691bf5d402 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Mon, 5 Aug 2024 15:38:13 -0700 Subject: [PATCH 1/4] working sh script --- ui/litellm-dashboard/build_ui_custom_path.sh | 59 ++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 ui/litellm-dashboard/build_ui_custom_path.sh diff --git a/ui/litellm-dashboard/build_ui_custom_path.sh b/ui/litellm-dashboard/build_ui_custom_path.sh new file mode 100644 index 000000000..11b054b59 --- /dev/null +++ b/ui/litellm-dashboard/build_ui_custom_path.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Check if BASE_UI_PATH argument is provided +if [ -z "$1" ]; then + echo "Error: BASE_UI_PATH argument is required." + echo "Usage: $0 " + exit 1 +fi + +# Set BASE_UI_PATH from the first argument +BASE_UI_PATH="$1" + +# Check if nvm is not installed +if ! command -v nvm &> /dev/null; then + # Install nvm + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash + + # Source nvm script in the current session + export NVM_DIR="$HOME/.nvm" + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" +fi + +# Use nvm to set the required Node.js version +nvm use v18.17.0 + +# Check if nvm use was successful +if [ $? -ne 0 ]; then + echo "Error: Failed to switch to Node.js v18.17.0. Deployment aborted." + exit 1 +fi + +# print contents of ui_colors.json +echo "Contents of ui_colors.json:" +cat ui_colors.json + +# Run npm build with the environment variable +BASE_UI_PATH=$BASE_UI_PATH npm run build + +# Check if the build was successful +if [ $? -eq 0 ]; then + echo "Build successful. Copying files..." + + # echo current dir + echo + pwd + + # Specify the destination directory + destination_dir="../../litellm/proxy/_experimental/out" + + # Remove existing files in the destination directory + rm -rf "$destination_dir"/* + + # Copy the contents of the output directory to the specified destination + cp -r ./out/* "$destination_dir" + + echo "Deployment completed." +else + echo "Build failed. Deployment aborted." +fi \ No newline at end of file From 900e89c0adc717d2b22621703ede3347f216b280 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Mon, 5 Aug 2024 15:48:44 -0700 Subject: [PATCH 2/4] set PROXY_BASE_URL when server root path set --- litellm/proxy/proxy_server.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index a9b49138b..17b23a361 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -281,9 +281,12 @@ except Exception as e: except Exception as e: pass +server_root_path = os.getenv("SERVER_ROOT_PATH", "") +if server_root_path != "" and os.getenv("PROXY_BASE_URL") is None: + os.environ["PROXY_BASE_URL"] = server_root_path _license_check = LicenseCheck() premium_user: bool = _license_check.is_premium() -ui_link = f"/ui/" +ui_link = f"{server_root_path}/ui/" ui_message = ( f"👉 [```LiteLLM Admin Panel on /ui```]({ui_link}). Create, Edit Keys with SSO" ) @@ -303,14 +306,13 @@ _description = ( else f"Proxy Server to call 100+ LLMs in the OpenAI format. {custom_swagger_message}\n\n{ui_message}" ) + app = FastAPI( docs_url=_docs_url, title=_title, description=_description, version=version, - root_path=os.environ.get( - "SERVER_ROOT_PATH", "" - ), # check if user passed root path, FastAPI defaults this value to "" + root_path=server_root_path, # check if user passed root path, FastAPI defaults this value to "" ) From dab556660db5330a9d1ab5fc4c1ff4c9ac97701c Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Mon, 5 Aug 2024 15:59:50 -0700 Subject: [PATCH 3/4] use correct build paths --- ui/litellm-dashboard/build_ui_custom_path.sh | 12 ++++++------ ui/litellm-dashboard/next.config.mjs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) mode change 100644 => 100755 ui/litellm-dashboard/build_ui_custom_path.sh diff --git a/ui/litellm-dashboard/build_ui_custom_path.sh b/ui/litellm-dashboard/build_ui_custom_path.sh old mode 100644 new mode 100755 index 11b054b59..ceb8c733d --- a/ui/litellm-dashboard/build_ui_custom_path.sh +++ b/ui/litellm-dashboard/build_ui_custom_path.sh @@ -1,14 +1,14 @@ #!/bin/bash -# Check if BASE_UI_PATH argument is provided +# Check if UI_BASE_PATH argument is provided if [ -z "$1" ]; then - echo "Error: BASE_UI_PATH argument is required." - echo "Usage: $0 " + echo "Error: UI_BASE_PATH argument is required." + echo "Usage: $0 " exit 1 fi -# Set BASE_UI_PATH from the first argument -BASE_UI_PATH="$1" +# Set UI_BASE_PATH from the first argument +UI_BASE_PATH="$1" # Check if nvm is not installed if ! command -v nvm &> /dev/null; then @@ -34,7 +34,7 @@ echo "Contents of ui_colors.json:" cat ui_colors.json # Run npm build with the environment variable -BASE_UI_PATH=$BASE_UI_PATH npm run build +UI_BASE_PATH=$UI_BASE_PATH npm run build # Check if the build was successful if [ $? -eq 0 ]; then diff --git a/ui/litellm-dashboard/next.config.mjs b/ui/litellm-dashboard/next.config.mjs index e1f8aa083..6e2924677 100644 --- a/ui/litellm-dashboard/next.config.mjs +++ b/ui/litellm-dashboard/next.config.mjs @@ -1,7 +1,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { output: 'export', - basePath: '/ui', + basePath: process.env.UI_BASE_PATH || '/ui', }; nextConfig.experimental = { From 091449e81bf1f8e14de6b4fa92624409441d4bdb Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Mon, 5 Aug 2024 16:34:37 -0700 Subject: [PATCH 4/4] build ui on custom path --- litellm/proxy/common_utils/admin_ui_utils.py | 65 ++++++++++++++++++++ litellm/proxy/proxy_server.py | 5 +- ui/litellm-dashboard/build_ui_custom_path.sh | 4 -- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/litellm/proxy/common_utils/admin_ui_utils.py b/litellm/proxy/common_utils/admin_ui_utils.py index bb35ecd69..3389f723d 100644 --- a/litellm/proxy/common_utils/admin_ui_utils.py +++ b/litellm/proxy/common_utils/admin_ui_utils.py @@ -1,4 +1,5 @@ import os +import subprocess def show_missing_vars_in_env(): @@ -165,3 +166,67 @@ def missing_keys_form(missing_key_names: str): """ return missing_keys_html_form.format(missing_keys=missing_key_names) + + +def setup_admin_ui_on_server_root_path(): + """ + Helper util to setup Admin UI on Server root path + """ + from litellm._logging import verbose_proxy_logger + + server_root_path = os.getenv("SERVER_ROOT_PATH", "") + if server_root_path != "": + if os.getenv("PROXY_BASE_URL") is None: + os.environ["PROXY_BASE_URL"] = server_root_path + + # re-build admin UI on server root path + # Save the original directory + original_dir = os.getcwd() + + current_dir = ( + os.path.dirname(os.path.abspath(__file__)) + + "/../../../ui/litellm-dashboard/" + ) + build_ui_path = os.path.join(current_dir, "build_ui_custom_path.sh") + package_path = os.path.join(current_dir, "package.json") + + verbose_proxy_logger.debug( + f"Setting up Admin UI on {server_root_path}/ui ......." + ) # noqa + + try: + # Change the current working directory + os.chdir(current_dir) + + # Make the script executable + subprocess.run(["chmod", "+x", "build_ui_custom_path.sh"], check=True) + + # Run npm install + subprocess.run(["npm", "install"], check=True) + + # Run npm run build + subprocess.run(["npm", "run", "build"], check=True) + + # Run the custom build script with the argument + subprocess.run( + ["./build_ui_custom_path.sh", f"{server_root_path}/ui"], check=True + ) + + verbose_proxy_logger.debug("Admin UI setup completed successfully.") # noqa + + except subprocess.CalledProcessError as e: + verbose_proxy_logger.debug( + f"An error occurred during the Admin UI setup: {e}" + ) # noqa + + except Exception as e: + verbose_proxy_logger.debug(f"An unexpected error occurred: {e}") + + finally: + # Always return to the original directory, even if an error occurred + os.chdir(original_dir) + verbose_proxy_logger.debug( + f"Returned to original directory: {original_dir}" + ) # noqa + + pass diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 17b23a361..260c728b5 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -138,6 +138,7 @@ from litellm.proxy.auth.user_api_key_auth import user_api_key_auth from litellm.proxy.caching_routes import router as caching_router from litellm.proxy.common_utils.admin_ui_utils import ( html_form, + setup_admin_ui_on_server_root_path, show_missing_vars_in_env, ) from litellm.proxy.common_utils.debug_utils import router as debugging_endpoints_router @@ -282,8 +283,8 @@ except Exception as e: pass server_root_path = os.getenv("SERVER_ROOT_PATH", "") -if server_root_path != "" and os.getenv("PROXY_BASE_URL") is None: - os.environ["PROXY_BASE_URL"] = server_root_path +if server_root_path != "": + setup_admin_ui_on_server_root_path() _license_check = LicenseCheck() premium_user: bool = _license_check.is_premium() ui_link = f"{server_root_path}/ui/" diff --git a/ui/litellm-dashboard/build_ui_custom_path.sh b/ui/litellm-dashboard/build_ui_custom_path.sh index ceb8c733d..f947f87d3 100755 --- a/ui/litellm-dashboard/build_ui_custom_path.sh +++ b/ui/litellm-dashboard/build_ui_custom_path.sh @@ -29,10 +29,6 @@ if [ $? -ne 0 ]; then exit 1 fi -# print contents of ui_colors.json -echo "Contents of ui_colors.json:" -cat ui_colors.json - # Run npm build with the environment variable UI_BASE_PATH=$UI_BASE_PATH npm run build