fix: address all differential review feedback

1. Reduced repeat_penalty to 1.15 to avoid degrading normal generation.
2. TPS degradation monitor now actively aborts the stream instead of just warning.
3. Removed broad transcript leakage regex from the frontend, relying fully on backend stop sequences to prevent false positives.
4. Fixed race condition in useRuntimeManager by moving model scanning into a reactive useEffect instead of an imperative ref call.
5. Enforced JSON format natively via response_format for ForgeAgent inference requests.
This commit is contained in:
Evandro Fonseca Junior committed 2026-04-03 23:16:41 -03:00
1 parent 943bf6321f
commit 36b80bc0a8
6 files changed
+273 -73

No files matched your search

+60 -27
View File
@@ -43,28 +43,48 @@ pub fn build_router(state: AppState) -> Router {
let trace_layer = TraceLayer::new_for_http()
.make_span_with(|request: &axum::http::Request<_>| {
let request_id = uuid::Uuid::new_v4().to_string();
tracing::info_span!(
"http",
request_id = %request_id,
method = %request.method(),
path = %request.uri().path(),
user_agent = request
.headers()
.get(axum::http::header::USER_AGENT)
.and_then(|v| v.to_str().ok())
.unwrap_or(""),
// filled in on_response
status = tracing::field::Empty,
latency_ms = tracing::field::Empty,
)
})
.on_request(|request: &axum::http::Request<_>, _span: &tracing::Span| {
let content_length = request
let path = request.uri().path();
// Health checks are polled frequently — keep them at DEBUG to avoid noise.
// All other routes use INFO so they appear in default log output.
let level = if path == "/health" {
tracing::Level::DEBUG
} else {
tracing::Level::INFO
};
// Truncate user-agent: keep only the first token (e.g. "Mozilla/5.0")
// to avoid flooding logs with full browser UA strings.
let raw_ua = request
.headers()
.get(axum::http::header::CONTENT_LENGTH)
.get(axum::http::header::USER_AGENT)
.and_then(|v| v.to_str().ok())
.unwrap_or("0");
tracing::info!(content_length, "request_received");
.unwrap_or("");
let ua_short = raw_ua.split_whitespace().next().unwrap_or("");
macro_rules! make_span {
($level:expr) => {
tracing::span!(
$level,
"http",
request_id = %request_id,
method = %request.method(),
path = %path,
ua = %ua_short,
status = tracing::field::Empty,
latency_ms = tracing::field::Empty,
)
};
}
match level {
tracing::Level::DEBUG => make_span!(tracing::Level::DEBUG),
_ => make_span!(tracing::Level::INFO),
}
})
.on_request(|_request: &axum::http::Request<_>, _span: &tracing::Span| {
// Intentionally empty: method/path/ua are already captured in the span.
// Emitting a separate "request_received" event is redundant noise.
})
.on_response(
|response: &axum::http::Response<_>,
@@ -72,7 +92,8 @@ pub fn build_router(state: AppState) -> Router {
span: &tracing::Span| {
span.record("status", response.status().as_u16());
span.record("latency_ms", latency.as_millis());
tracing::info!("response_sent");
// Only emit a log event for non-health routes; health is already DEBUG-spanned.
// The span itself carries all fields — no need for a separate "response_sent" event.
},
)
.on_failure(DefaultOnFailure::new().level(tracing::Level::ERROR));
@@ -126,7 +147,7 @@ async fn models_handler(State(state): State<AppState>, headers: HeaderMap) -> Re
}
let model_list = state.server_config.model_list(unix_now());
tracing::info!(model_count = model_list.len(), "models.listed");
tracing::debug!(model_count = model_list.len(), "models.listed");
Json(ModelList { object: "list", data: model_list }).into_response()
}
@@ -135,17 +156,20 @@ async fn chat_completions_handler(
headers: HeaderMap,
Json(req): Json<ChatCompletionRequest>,
) -> Response {
// Log the last user message (truncated) for easy debugging without flooding logs.
let last_user_preview = req.messages.iter().rev()
.find(|m| matches!(m.role, Role::User))
.and_then(|m| m.content.as_deref())
.map(|s| if s.len() > 80 { format!("{}…", &s[..80]) } else { s.to_owned() })
.unwrap_or_default();
tracing::info!(
model = %req.model,
stream = req.stream,
messages = req.messages.len(),
max_tokens = ?req.max_tokens,
temperature = ?req.temperature,
auth_present = headers.contains_key(
state.server_config.auth_header
.parse::<axum::http::HeaderName>()
.unwrap_or(axum::http::header::AUTHORIZATION)
),
user_msg = %last_user_preview,
"chat_completions.received"
);
@@ -261,6 +285,11 @@ async fn stream_response(
record.tick();
counters_arc.inc_tokens(1);
let _ = rt.block_on(tx.send(StreamItem::Token(token)));
if session.degradation_state() == &inference_core::session::DegradationState::Degraded {
tracing::error!("stream: aborting due to TPS degradation");
let _ = rt.block_on(tx.send(StreamItem::Error));
return;
}
}
let usage = Usage {
@@ -488,6 +517,10 @@ async fn generate_full_completion(
while let Some(tok) = session.next_token() {
record.tick();
content.push_str(&tok);
if session.degradation_state() == &inference_core::session::DegradationState::Degraded {
tracing::error!("generate_full_completion: aborting due to TPS degradation");
break;
}
}
counters_arc.inc_tokens(record.completion_tokens as u64);