Expose diagnose environment details

Co-authored-by: ishaan-berri <ishaan-berri@users.noreply.github.com>
This commit is contained in:
oss-agent-shin 2026-05-06 01:49:26 +00:00
parent 53f8a4cac5
commit 22ff909283
No known key found for this signature in database
2 changed files with 82 additions and 14 deletions

View file

@ -11,6 +11,7 @@ from datetime import datetime, timedelta
from typing import Any, Dict, Iterable, Literal, Optional, Union, cast
import fastapi
import yaml
from fastapi import APIRouter, Depends, HTTPException, Request, Response, status
from pydantic import BaseModel, Field
@ -184,6 +185,57 @@ def _get_litellm_package_version() -> str:
return "unknown"
def _get_litellm_installation_info() -> dict:
try:
distribution = importlib.metadata.distribution("litellm")
except importlib.metadata.PackageNotFoundError:
distribution = None
installer = distribution.read_text("INSTALLER") if distribution else None
is_container_runtime = os.path.exists("/.dockerenv") or bool(
os.getenv("KUBERNETES_SERVICE_HOST")
)
package_manager = (installer or "unknown").strip() or "unknown"
return {
"runtime": "docker_or_container" if is_container_runtime else "bare_python",
"is_docker_or_container": is_container_runtime,
"install_source": (
"docker_or_container" if is_container_runtime else package_manager
),
"package_manager": package_manager,
"package_location": str(distribution.locate_file("")) if distribution else None,
"has_direct_url_metadata": (
distribution.read_text("direct_url.json") is not None
if distribution
else False
),
}
def _dump_diagnose_config_yaml(redacted_config: Any) -> str:
return yaml.safe_dump(redacted_config, sort_keys=False)
def _build_diagnose_response(
*,
used_llm: bool,
selected_model: Optional[str],
diagnostic_report: str,
diagnostic_context: dict,
) -> dict:
return {
"used_llm": used_llm,
"selected_model": selected_model,
"litellm_version": diagnostic_context["litellm_version"],
"installation": diagnostic_context["installation"],
"redacted_config_yaml": diagnostic_context["redacted_config_yaml"],
"redacted_config": diagnostic_context["config"],
"diagnostic_report": diagnostic_report,
"diagnostic_context": diagnostic_context,
}
def _get_diagnose_model_list(llm_router: Optional[Any]) -> list:
if llm_router is None:
return []
@ -215,8 +267,9 @@ def _build_diagnose_prompt(
"You are helping the LiteLLM team reproduce a proxy issue. "
"Act like a concise support engineer doing a mini diagnostic grill: "
"identify the exact LiteLLM version, summarize the configured proxy models, "
"highlight relevant YAML/config settings, list missing details to ask the "
"admin, and produce clean Markdown reproduction steps.\n\n"
"state whether the deployment appears to be Docker/container or pip-installed, "
"highlight relevant YAML/config settings, list missing details to ask the admin, "
"and produce clean Markdown reproduction steps.\n\n"
f"Model selected for this diagnostic LLM call: {selected_model}\n"
f"Issue description from admin: {request.issue_description or 'Not provided'}\n"
f"Known reproduction steps from admin: {request.reproduction_steps or 'Not provided'}\n\n"
@ -1703,11 +1756,14 @@ async def diagnose_endpoint(
)
redacted_config = _redact_diagnose_payload(proxy_config.get_config_state())
redacted_models = _redact_diagnose_payload(configured_models)
redacted_config_yaml = _dump_diagnose_config_yaml(redacted_config)
diagnostic_context = {
"litellm_version": _get_litellm_package_version(),
"installation": _get_litellm_installation_info(),
"python_version": sys.version,
"configured_models": redacted_models,
"config": redacted_config,
"redacted_config_yaml": redacted_config_yaml,
"admin_user": {
"user_id": user_api_key_dict.user_id,
"user_role": (
@ -1719,10 +1775,10 @@ async def diagnose_endpoint(
}
if selected_model is None or llm_router is None:
return {
"used_llm": False,
"selected_model": selected_model,
"diagnostic_report": (
return _build_diagnose_response(
used_llm=False,
selected_model=selected_model,
diagnostic_report=(
"# LiteLLM Diagnostic Report\n\n"
"No proxy model is configured for the diagnostic LLM call. "
"Call `/diagnose` again with a configured `model`, or add a "
@ -1730,8 +1786,8 @@ async def diagnose_endpoint(
"Markdown reproduction report.\n\n"
f"```json\n{json.dumps(diagnostic_context, indent=2, sort_keys=True, default=str)}\n```"
),
"diagnostic_context": diagnostic_context,
}
diagnostic_context=diagnostic_context,
)
prompt = _build_diagnose_prompt(
request=diagnose_request,
@ -1743,12 +1799,12 @@ async def diagnose_endpoint(
messages=[{"role": "user", "content": prompt}],
temperature=0.0,
)
return {
"used_llm": True,
"selected_model": selected_model,
"diagnostic_report": _extract_diagnose_response_text(response),
"diagnostic_context": diagnostic_context,
}
return _build_diagnose_response(
used_llm=True,
selected_model=selected_model,
diagnostic_report=_extract_diagnose_response_text(response),
diagnostic_context=diagnostic_context,
)
@router.get(

View file

@ -730,6 +730,15 @@ def test_diagnose_generates_redacted_llm_report(monkeypatch):
response_data = response.json()
assert response_data["selected_model"] == "gpt-4o"
assert response_data["used_llm"] is True
assert response_data["litellm_version"]
assert response_data["installation"]["runtime"] in (
"docker_or_container",
"bare_python",
)
assert response_data["redacted_config"]["general_settings"]["master_key"] == (
"[REDACTED]"
)
assert "master_key: '[REDACTED]'" in response_data["redacted_config_yaml"]
assert response_data["diagnostic_report"].startswith("# Reproduction report")
assert captured_call["model"] == "gpt-4o"
@ -768,6 +777,9 @@ def test_diagnose_prompts_for_model_when_no_llm_is_configured(monkeypatch):
response_data = response.json()
assert response_data["used_llm"] is False
assert response_data["selected_model"] is None
assert response_data["litellm_version"]
assert response_data["installation"]["install_source"]
assert "master_key: '[REDACTED]'" in response_data["redacted_config_yaml"]
assert "configured `model`" in response_data["diagnostic_report"]
assert "sk-master-secret" not in response_data["diagnostic_report"]