Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion backends/exllamav3/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from common.health import HealthManager
from common.errors import ContextLengthExceededError, validate_context_requirements
from common.logger import xlogger
from common.metrics import MetricsManager
from common.multimodal import MultimodalEmbeddingWrapper
from common.networking import DisconnectHandler
from common.optional_dependencies import check_package_version
Expand Down Expand Up @@ -351,6 +352,12 @@ async def create(cls, model_directory: pathlib.Path, hf_model: HFModel, **kwargs
self.max_seq_len = max_seq_len
self.cache_size = cache_size

# Size the /metrics token histograms to this model's context length.
# Their buckets are meaningless until the range they have to cover is
# known, and a ladder that overshoots it reports percentiles above any
# request the server can even accept.
MetricsManager.configure_token_buckets(max_seq_len)

# Max batch size
default_mbs = 4 if self.model.caps.get("recurrent_states") else 128
self.max_batch_size = unwrap(kwargs.get("max_batch_size"), default_mbs)
Expand Down Expand Up @@ -1065,7 +1072,8 @@ def handle_finish_chunk(self, result: dict, request_id: str, full_text: str):
# Prompt
prompt_tokens = result.get("prompt_tokens")
cached_tokens = round(result.get("cached_tokens"), 2)
prompt_time = round(result.get("time_prefill"), 2)
raw_prompt_time = result.get("time_prefill")
prompt_time = round(raw_prompt_time, 2)
prompt_ts = (
"Indeterminate"
if prompt_time == 0
Expand Down Expand Up @@ -1111,6 +1119,20 @@ def handle_finish_chunk(self, result: dict, request_id: str, full_text: str):
}
)

# Accumulate server-wide metrics for the /metrics endpoint
MetricsManager.record_generation(
prompt_tokens=prompt_tokens,
cached_tokens=cached_tokens,
gen_tokens=gen_tokens,
# Unrounded, so the aggregate rates are not skewed by the 0.01s
# display rounding on short prefills.
prompt_time=raw_prompt_time,
gen_time=gen_time,
queue_time=queue_time,
accepted_draft_tokens=accepted_draft_tokens,
rejected_draft_tokens=rejected_draft_tokens,
)

return finish_chunk

async def generate_gen(
Expand Down
8 changes: 8 additions & 0 deletions common/config_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ class NetworkConfig(BaseConfigModel):
),
ge=0,
)
enable_metrics: Optional[bool] = Field(
False,
description=(
"Enable the Prometheus-compatible /metrics endpoint (default: False).\n"
"Exposes aggregate inference stats in the text exposition format.\n"
"NOTE: This endpoint is not protected by API key authentication."
),
)

# Converts all strings in the api_servers list to lowercase
# NOTE: Expand if more models need this validator
Expand Down
Loading