mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-29 06:33:28 +00:00
fix(proxy): keep show_banner() SDK-free, pick the JSON banner in initialize()
Since #46803 the `lite` shell calls show_banner() against an uninitialized litellm package, and reading litellm.json_logs inside it initialized the whole SDK at the banner (0.14 s to 0.83 s for a bare `lite` here, the seconds that PR removed on small VMs). show_banner() is back to its main version; the proxy's initialize() now emits the JSON banner record itself and calls show_banner() only in plain mode. The banner unit tests move to the initialize() call site.
This commit is contained in:
parent
4fa139f8c0
commit
e2303a3925
4 changed files with 41 additions and 44 deletions
|
|
@ -11,12 +11,6 @@ LITELLM_BANNER: Final = """ ██╗ ██╗████████╗
|
||||||
|
|
||||||
def show_banner():
|
def show_banner():
|
||||||
"""Display the LiteLLM CLI banner."""
|
"""Display the LiteLLM CLI banner."""
|
||||||
import litellm
|
|
||||||
from litellm._logging import print_startup_message
|
|
||||||
|
|
||||||
if litellm.json_logs:
|
|
||||||
print_startup_message(LITELLM_BANNER)
|
|
||||||
return
|
|
||||||
try:
|
try:
|
||||||
import click
|
import click
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9550,9 +9550,14 @@ async def initialize(
|
||||||
master_key, \
|
master_key, \
|
||||||
user_custom_auth, \
|
user_custom_auth, \
|
||||||
prisma_client
|
prisma_client
|
||||||
from litellm.proxy.common_utils.banner import show_banner
|
from litellm.proxy.common_utils.banner import LITELLM_BANNER, show_banner
|
||||||
|
|
||||||
show_banner()
|
# show_banner() also serves the `lite` shell, which runs against an uninitialized SDK (#46803), so
|
||||||
|
# the JSON-mode choice stays out of it.
|
||||||
|
if litellm.json_logs:
|
||||||
|
print_startup_message(LITELLM_BANNER)
|
||||||
|
else:
|
||||||
|
show_banner()
|
||||||
if os.getenv("LITELLM_DONT_SHOW_FEEDBACK_BOX", "").lower() != "true":
|
if os.getenv("LITELLM_DONT_SHOW_FEEDBACK_BOX", "").lower() != "true":
|
||||||
generate_feedback_box()
|
generate_feedback_box()
|
||||||
user_model = model
|
user_model = model
|
||||||
|
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
"""The CLI banner is terminal art in plain mode and one JSON record when json_logs is on."""
|
|
||||||
|
|
||||||
import json
|
|
||||||
import sys
|
|
||||||
from typing import Final
|
|
||||||
|
|
||||||
import litellm
|
|
||||||
from litellm._logging import turn_on_json
|
|
||||||
from litellm.proxy.common_utils.banner import LITELLM_BANNER, show_banner
|
|
||||||
|
|
||||||
|
|
||||||
def test_show_banner_prints_the_banner_between_blank_lines_in_plain_mode(monkeypatch, capfd):
|
|
||||||
"""Operators without JSON logs see the banner exactly as before."""
|
|
||||||
monkeypatch.setattr(litellm, "json_logs", False)
|
|
||||||
|
|
||||||
show_banner()
|
|
||||||
|
|
||||||
assert capfd.readouterr() == (f"\n{LITELLM_BANNER}\n\n", "")
|
|
||||||
|
|
||||||
|
|
||||||
def test_show_banner_is_one_json_record_in_json_mode(monkeypatch, capfd):
|
|
||||||
"""With JSON logs on, the six banner rows are one INFO record with their indentation kept, so the
|
|
||||||
first line a worker writes parses like every other."""
|
|
||||||
monkeypatch.setattr(litellm, "json_logs", True)
|
|
||||||
monkeypatch.setattr(sys, "excepthook", sys.excepthook) # turn_on_json swaps it; put it back at teardown
|
|
||||||
turn_on_json()
|
|
||||||
|
|
||||||
show_banner()
|
|
||||||
|
|
||||||
out, err = capfd.readouterr()
|
|
||||||
assert err == ""
|
|
||||||
lines: Final = [raw for raw in out.splitlines() if raw.strip()]
|
|
||||||
assert len(lines) == 1, lines
|
|
||||||
record: Final = json.loads(lines[0])
|
|
||||||
assert record["message"] == LITELLM_BANNER
|
|
||||||
assert record["level"] == "INFO"
|
|
||||||
|
|
@ -48,6 +48,7 @@ from litellm.proxy.auth.user_api_key_auth import user_api_key_auth
|
||||||
from litellm.proxy.hooks.parallel_request_limiter_v3 import RequestRateLimiterStash
|
from litellm.proxy.hooks.parallel_request_limiter_v3 import RequestRateLimiterStash
|
||||||
from litellm.proxy.proxy_server import app, aws_error_type_exception_handler, initialize, openai_exception_handler
|
from litellm.proxy.proxy_server import app, aws_error_type_exception_handler, initialize, openai_exception_handler
|
||||||
from litellm.utils import _invalidate_model_cost_lowercase_map
|
from litellm.utils import _invalidate_model_cost_lowercase_map
|
||||||
|
from litellm.proxy.common_utils.banner import LITELLM_BANNER
|
||||||
from tests._master_key import MASTER_KEY
|
from tests._master_key import MASTER_KEY
|
||||||
|
|
||||||
PUBLICLY_KNOWN_KEY: Final = "sk-" + "1234"
|
PUBLICLY_KNOWN_KEY: Final = "sk-" + "1234"
|
||||||
|
|
@ -15725,3 +15726,36 @@ def test_feedback_box_is_one_json_record_in_json_mode(monkeypatch, capfd):
|
||||||
assert "Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new" in record["message"]
|
assert "Give Feedback / Get Help: https://github.com/BerriAI/litellm/issues/new" in record["message"]
|
||||||
assert "Thank you for using LiteLLM! - Krrish & Ishaan" in record["message"]
|
assert "Thank you for using LiteLLM! - Krrish & Ishaan" in record["message"]
|
||||||
assert "\x1b[" not in record["message"]
|
assert "\x1b[" not in record["message"]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_initialize_prints_the_banner_between_blank_lines_in_plain_mode(monkeypatch, capfd):
|
||||||
|
"""Operators without JSON logs see the banner exactly as before, through show_banner()'s flushing
|
||||||
|
click.echo."""
|
||||||
|
monkeypatch.setattr(litellm, "json_logs", False)
|
||||||
|
monkeypatch.setenv("LITELLM_DONT_SHOW_FEEDBACK_BOX", "true")
|
||||||
|
|
||||||
|
await proxy_server_module.initialize()
|
||||||
|
|
||||||
|
out, err = capfd.readouterr()
|
||||||
|
assert err == ""
|
||||||
|
assert out.startswith(f"\n{LITELLM_BANNER}\n\n"), out
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_initialize_prints_the_banner_as_one_json_record_in_json_mode(monkeypatch, capfd):
|
||||||
|
"""With JSON logs on, the six banner rows are one INFO record with their indentation kept, so the
|
||||||
|
first line a worker writes parses like every other."""
|
||||||
|
monkeypatch.setattr(litellm, "json_logs", True)
|
||||||
|
monkeypatch.setattr(sys, "excepthook", sys.excepthook) # turn_on_json swaps it; put it back at teardown
|
||||||
|
monkeypatch.setenv("LITELLM_DONT_SHOW_FEEDBACK_BOX", "true")
|
||||||
|
turn_on_json()
|
||||||
|
|
||||||
|
await proxy_server_module.initialize()
|
||||||
|
|
||||||
|
out, err = capfd.readouterr()
|
||||||
|
assert err == ""
|
||||||
|
records: Final = [json.loads(raw) for raw in out.splitlines() if raw.strip()]
|
||||||
|
banner_records: Final = [record for record in records if record["message"] == LITELLM_BANNER]
|
||||||
|
assert len(banner_records) == 1, records
|
||||||
|
assert banner_records[0]["level"] == "INFO"
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue