Skip to content

fix(ui): harden Token Router running model and detail views - #5399

Open
m199369309 wants to merge 32 commits into
xorbitsai:mainfrom
m199369309:fix/token-router-ui-hardening
Open

fix(ui): harden Token Router running model and detail views#5399
m199369309 wants to merge 32 commits into
xorbitsai:mainfrom
m199369309:fix/token-router-ui-hardening

Conversation

@m199369309

Copy link
Copy Markdown
Collaborator

Summary

  • support Token Router virtual models in the Running Model page and detail view
  • filter disabled or unavailable Token Router entries from physical-model operations
  • show virtual-model, Router, Runtime, deployment, and node details with safe fallbacks
  • load Runtime and assignment information independently so partial API failures do not hide Router configuration
  • normalize sparse and legacy Router configuration before editing or saving
  • preserve backend defaults for managed backends and avoid duplicate error notifications
  • support virtual-model requests in the Try To API flow
  • add English, Chinese, Japanese, and Korean strings for the new Runtime and virtual-model states

Dependency

The identifier-label and Tokenizer Asset layout changes from #5393 are intentionally excluded from this PR to avoid duplicate submission.

Validation

  • git diff --check
  • npx prettier --check <changed frontend files>
  • npx eslint <changed frontend files>
  • npm run build
  • pre-commit run --files <changed frontend files> (Python hooks skipped because the change is frontend-only)

The build completed successfully. Next.js reported only existing repository warnings in unrelated files.

…deepseek-tokenizer-asset

# Conflicts:
#	xinference/core/supervisor.py
…agent-orchestration

# Conflicts:
#	xinference/api/tests/test_token_router_api.py
#	xinference/core/supervisor.py
#	xinference/router/app.py
@XprobeBot XprobeBot added the bug Something isn't working label Aug 20, 2026
@XprobeBot XprobeBot added this to the v3.x milestone Aug 20, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the 'Token Router' feature to Xinference, enabling token-budget routing between short- and long-context model backends. It adds comprehensive frontend management interfaces, i18n support, RESTful API endpoints, and a backend orchestration controller to manage Router Nodes, Assignments, and Tokenizer Assets. Feedback from the review highlights critical improvements: utilizing Starlette's 'BackgroundTask' to prevent connection leaks during early client disconnects in the streaming proxy, wrapping blocking SQLite operations in 'asyncio.to_thread' to keep the main event loop responsive, and refactoring the monolithic validation in the frontend form dialog to provide more specific and helpful error messages.

Comment on lines +632 to +638
response_headers.setdefault("cache-control", "no-cache")
response_headers.setdefault("x-accel-buffering", "no")
return StreamingResponse(
body_stream(),
status_code=upstream_response.status_code,
headers=response_headers,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If the client disconnects before the stream starts iterating, the generator's finally block is never executed, which can leak the upstream_response connection. To prevent this, use a Starlette BackgroundTask to guarantee that upstream_response.aclose() is called upon response completion or early disconnect.

            from starlette.background import BackgroundTask

            response_headers.setdefault("cache-control", "no-cache")
            response_headers.setdefault("x-accel-buffering", "no")
            return StreamingResponse(
                body_stream(),
                status_code=upstream_response.status_code,
                headers=response_headers,
                background=BackgroundTask(upstream_response.aclose),
            )
References
  1. When managing critical concurrency resources in a streaming response, use a Starlette BackgroundTask as an early-disconnect fallback alongside generator finally blocks.

async def _monitor_token_router_nodes(self) -> None:
while True:
try:
transitions = self._token_router_orchestration.sweep_nodes()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

sweep_nodes() performs blocking SQLite database operations (such as updating node connectivity status and marking bindings stale). Running this directly on the async event loop can block the loop and cause latency spikes. Use asyncio.to_thread to run it in a separate thread, keeping the event loop responsive.

Suggested change
transitions = self._token_router_orchestration.sweep_nodes()
transitions = await asyncio.to_thread(self._token_router_orchestration.sweep_nodes)

Comment on lines +393 to +423
if (
typedDraft.backends.length < 1 ||
typedDraft.backends.length > 16 ||
typedDraft.rules.length < 1 ||
typedDraft.rules.length > 64 ||
typedDraft.backends.some(
(backend) =>
!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(backend.id.trim()) ||
!backend.model_uid.trim() ||
backend.max_context_tokens < 1 ||
backend.admission.max_active < 1 ||
backend.admission.max_queue < 0
) ||
new Set(backendIds).size !== backendIds.length ||
typedDraft.rules.some(
(rule) =>
!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$/.test(rule.id.trim()) ||
rule.priority < 1 ||
rule.priority > 10000
) ||
new Set(ruleIds).size !== ruleIds.length ||
new Set(priorities).size !== priorities.length ||
invalidRule ||
(typedDraft.defaultAction.type === 'route'
? !backendIds.includes(typedDraft.defaultAction.backend_id)
: !typedDraft.defaultAction.reason.trim())
) {
toast.error(t('tokenRouter.validation.invalidAdvancedConfig'));
setSaving(false);
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of a single monolithic if statement with a generic error message, consider performing individual checks and showing specific error messages (e.g., "Duplicate backend IDs", "Duplicate rule priorities", "Invalid token range in rule X", etc.). This will significantly improve the developer and operator experience when configuring complex routing rules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants