mirror of
https://github.com/tiennm99/litellm.git
synced 2026-08-07 00:24:03 +00:00
feat(proxy_server.py): support checking full str on streaming guardrails post call hook
ensures streaming guardrails are actually useful
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -730,8 +730,11 @@ class ProxyBaseLLMRequestProcessing:
|
||||
"""
|
||||
Anthropic /messages and Google /generateContent streaming data generator require SSE events
|
||||
"""
|
||||
from litellm.types.utils import ModelResponse, ModelResponseStream
|
||||
|
||||
verbose_proxy_logger.debug("inside generator")
|
||||
try:
|
||||
str_so_far = ""
|
||||
async for chunk in response:
|
||||
verbose_proxy_logger.debug(
|
||||
"async_data_generator: received streaming chunk - {}".format(chunk)
|
||||
@@ -741,8 +744,13 @@ class ProxyBaseLLMRequestProcessing:
|
||||
user_api_key_dict=user_api_key_dict,
|
||||
response=chunk,
|
||||
data=request_data,
|
||||
str_so_far=str_so_far,
|
||||
)
|
||||
|
||||
if isinstance(chunk, (ModelResponse, ModelResponseStream)):
|
||||
response_str = litellm.get_response_string(response_obj=chunk)
|
||||
str_so_far += response_str
|
||||
|
||||
# Format chunk using helper function
|
||||
yield ProxyBaseLLMRequestProcessing.return_sse_chunk(chunk)
|
||||
except Exception as e:
|
||||
|
||||
@@ -147,7 +147,6 @@ from litellm.litellm_core_utils.credential_accessor import CredentialAccessor
|
||||
from litellm.litellm_core_utils.litellm_logging import Logging as LiteLLMLoggingObj
|
||||
from litellm.litellm_core_utils.sensitive_data_masker import SensitiveDataMasker
|
||||
from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler, HTTPHandler
|
||||
from litellm.types.realtime import RealtimeQueryParams
|
||||
from litellm.proxy._experimental.mcp_server.rest_endpoints import (
|
||||
router as mcp_rest_endpoints_router,
|
||||
)
|
||||
@@ -367,6 +366,7 @@ from litellm.types.proxy.management_endpoints.ui_sso import (
|
||||
DefaultTeamSSOParams,
|
||||
LiteLLM_UpperboundKeyGenerateParams,
|
||||
)
|
||||
from litellm.types.realtime import RealtimeQueryParams
|
||||
from litellm.types.router import DeploymentTypedDict
|
||||
from litellm.types.router import ModelInfo as RouterModelInfo
|
||||
from litellm.types.router import RouterGeneralSettings, updateDeployment
|
||||
@@ -3235,6 +3235,7 @@ async def async_data_generator(
|
||||
):
|
||||
verbose_proxy_logger.debug("inside generator")
|
||||
try:
|
||||
str_so_far = ""
|
||||
async for chunk in proxy_logging_obj.async_post_call_streaming_iterator_hook(
|
||||
user_api_key_dict=user_api_key_dict,
|
||||
response=response,
|
||||
@@ -3243,13 +3244,21 @@ async def async_data_generator(
|
||||
verbose_proxy_logger.debug(
|
||||
"async_data_generator: received streaming chunk - {}".format(chunk)
|
||||
)
|
||||
|
||||
|
||||
### CALL HOOKS ### - modify outgoing data
|
||||
chunk = await proxy_logging_obj.async_post_call_streaming_hook(
|
||||
user_api_key_dict=user_api_key_dict,
|
||||
response=chunk,
|
||||
data=request_data,
|
||||
str_so_far=str_so_far,
|
||||
)
|
||||
|
||||
|
||||
if isinstance(chunk, (ModelResponse, ModelResponseStream)):
|
||||
response_str = litellm.get_response_string(response_obj=chunk)
|
||||
str_so_far += response_str
|
||||
|
||||
if isinstance(chunk, BaseModel):
|
||||
chunk = chunk.model_dump_json(exclude_none=True, exclude_unset=True)
|
||||
|
||||
@@ -3538,7 +3547,7 @@ class ProxyStartupEvent:
|
||||
timezone=ZoneInfo("America/Los_Angeles"), # Pacific Time
|
||||
)
|
||||
await proxy_logging_obj.slack_alerting_instance.send_fallback_stats_from_prometheus()
|
||||
|
||||
|
||||
await cls._initialize_spend_tracking_background_jobs(scheduler=scheduler)
|
||||
|
||||
### SPEND LOG CLEANUP ###
|
||||
@@ -3587,12 +3596,14 @@ class ProxyStartupEvent:
|
||||
scheduler.start()
|
||||
|
||||
@classmethod
|
||||
async def _initialize_spend_tracking_background_jobs(cls, scheduler: AsyncIOScheduler):
|
||||
async def _initialize_spend_tracking_background_jobs(
|
||||
cls, scheduler: AsyncIOScheduler
|
||||
):
|
||||
"""
|
||||
Initialize the spend tracking background jobs
|
||||
1. CloudZero Background Job
|
||||
2. Prometheus Background Job
|
||||
|
||||
|
||||
Args:
|
||||
scheduler: The scheduler to add the background jobs to
|
||||
"""
|
||||
@@ -3606,7 +3617,7 @@ class ProxyStartupEvent:
|
||||
|
||||
if await is_cloudzero_setup_in_db():
|
||||
await init_cloudzero_background_job()
|
||||
|
||||
|
||||
########################################################
|
||||
# Prometheus Background Job
|
||||
########################################################
|
||||
@@ -3617,7 +3628,6 @@ class ProxyStartupEvent:
|
||||
PrometheusLogger.initialize_budget_metrics_cron_job(scheduler=scheduler)
|
||||
except Exception:
|
||||
PrometheusLogger = None
|
||||
|
||||
|
||||
@classmethod
|
||||
async def _setup_prisma_client(
|
||||
@@ -4681,7 +4691,9 @@ from litellm import _arealtime
|
||||
async def websocket_endpoint(
|
||||
websocket: WebSocket,
|
||||
model: str,
|
||||
intent: str = fastapi.Query(None, description="The intent of the websocket connection."),
|
||||
intent: str = fastapi.Query(
|
||||
None, description="The intent of the websocket connection."
|
||||
),
|
||||
user_api_key_dict=Depends(user_api_key_auth_websocket),
|
||||
):
|
||||
import websockets
|
||||
|
||||
@@ -1070,6 +1070,7 @@ class ProxyLogging:
|
||||
ModelResponse, EmbeddingResponse, ImageResponse, ModelResponseStream
|
||||
],
|
||||
user_api_key_dict: UserAPIKeyAuth,
|
||||
str_so_far: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Allow user to modify outgoing streaming data -> per chunk
|
||||
@@ -1110,8 +1111,13 @@ class ProxyLogging:
|
||||
else:
|
||||
_callback = callback # type: ignore
|
||||
if _callback is not None and isinstance(_callback, CustomLogger):
|
||||
if str_so_far is not None:
|
||||
complete_response = str_so_far + response_str
|
||||
else:
|
||||
complete_response = response_str
|
||||
await _callback.async_post_call_streaming_hook(
|
||||
user_api_key_dict=user_api_key_dict, response=response_str
|
||||
user_api_key_dict=user_api_key_dict,
|
||||
response=complete_response,
|
||||
)
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
Reference in New Issue
Block a user