Skip to content

feat(mtp-policy): expose the settled MTP verdict through a supported interface #1257

Closed

Description

@inureyes

Problem / Background

MtpPolicy (issue #333, src/server/batch/mtp_policy.rs) settles a per-pairing MTP verdict on the actual machine and persists it as a PolicyHint under ${MLXCEL_CACHE_DIR:-$HOME/.cache/mlxcel}/mtp-policy/<key-hash>.json. That verdict is the only honest, machine-specific answer to "does MTP help for this pairing here", and it is exactly what a host application wants to show a user.

Backend.AI GO is about to surface it (lablup/backend.ai-go#4441, epic lablup/backend.ai-go#4429). There is no API for it, so the only available path is to read mlxcel's cache directory from another process: enumerate mtp-policy/*.json, parse each file, and match on the body fields (target, drafter, block_size) rather than recomputing the SHA256 file stem.

That works, and it is coupling to a private on-disk format. HINT_VERSION is documented to bump whenever the schema or the verdict semantics change, HINT_SUBDIR is a private constant, and PolicyHint is pub(crate). Any of those can change in a patch release without notice, and the consumer has no way to learn about it except by silently showing nothing. The consumer already treats an unknown version, a missing directory, an unparseable file, and a block_size mismatch as "no verdict yet" rather than an error, so a format change degrades to a blank surface rather than a crash, but a blank surface is still a regression the user sees and neither project detects.

Proposed Solution

Expose the settled verdict through a supported interface. Either of these closes the gap; the first is preferred.

Option A, server API (preferred). Add a read-only endpoint that reports the current pairing's policy state, for example GET /v1/internal/mtp-policy returning the active (target, drafter, hardware, block_size) key plus verdict, acceptance_rate, samples, and whether the policy is still profiling (with PROFILE_SAMPLE_TARGET so a consumer can say how many more single-request generations are needed). A consumer then reads the verdict from the process that owns it, over the same transport it already uses, with no filesystem coupling and no cache-root resolution.

Option B, documented file contract. Keep the cache files as the interface but make them a contract: document the directory layout, the PolicyHint body, and the versioning rule in the repository docs; state which fields are stable; and treat a change to them as a breaking change with a HINT_VERSION bump plus a changelog entry.

Either way, the "still profiling" state deserves to be expressible. Today a consumer can only infer it from the absence of a file, which is indistinguishable from "the cache root resolved to the wrong place".

Acceptance Criteria

  • The settled MTP verdict for the running pairing is readable through a supported interface (API endpoint or documented file contract)
  • The interface distinguishes "settled: enable", "settled: decline", and "still profiling", and reports how many qualifying samples remain when profiling
  • The reported payload carries enough of the key (target, drafter, hardware, block_size) for a consumer to confirm the verdict describes the pairing it is showing
  • Versioning and the compatibility policy for the interface are documented
  • Backend.AI GO's interim cache read can be replaced by the supported interface

Implementation notes

Option A landed as GET /v1/internal/mtp-policy (src/server/routes/mtp_policy.rs), documented in docs/mtp-policy-api.md including the schema_version compatibility policy. The on-disk hints are untouched and keep working, so the shipped Backend.AI GO reader (lablup/backend.ai-go#4441) is not broken by this change; it can migrate to the endpoint at its own pace.

Beyond the three states the body asks for, the endpoint reports a fourth, forced (MLXCEL_ENABLE_MTP_B1 pinned the decision), separately from settled, because an operator pin is not a measured verdict. It also reports unavailable with a reason (no_mtp_dispatch, adaptive_disabled, worker_not_ready), which is what removes the "still profiling is indistinguishable from the cache root resolved to the wrong place" ambiguity named above.

Technical Considerations

Consumer side: lablup/backend.ai-go#4441 ships the cache read as the interim path, with a module doc comment naming this issue and stating plainly that it couples to a private on-disk format. Replacing it with whichever interface lands here is a small, localized change on that side.

Relevant constants at 4968b72e: HINT_VERSION = 3, HINT_SUBDIR = "mtp-policy", PROFILE_SAMPLE_TARGET = 4, ENABLE_SPEEDUP_FLOOR = 1.5, DECLINE_SPEEDUP_CEIL = 1.0. Cache root resolution is mlxcel_core::cache_root() (MLXCEL_CACHE_DIR, else $HOME/.cache/mlxcel).

Refs #333

Activity

  1. added
    type:enhancementNew features, capabilities, or significant additions
    area:inferenceGeneration, sampling, decoding (incl. speculative, DRY)
    area:architectureArchitecture and code structure changes
    on Aug 19, 2026
  2. inureyes commented on Aug 19, 2026

    @inureyes
    MemberAuthor

    Consumer side has landed: lablup/backend.ai-go#4441 reads the settled verdict from ${MLXCEL_CACHE_DIR:-$HOME/.cache/mlxcel}/mtp-policy/*.json as the interim path, matching on the hint body (target, drafter, block_size) rather than recomputing the SHA256 file stem, and treating a missing directory, an unreadable or unparseable file, a version other than 3, and a block_size mismatch all as "no verdict yet" rather than as errors. The reader's module doc states plainly that this couples to a private on-disk format and names this issue as its replacement.

  3. added a commit that references this issue on Aug 20, 2026
  4. self-assigned this
    on Aug 31, 2026
  5. added a commit that references this issue on Sep 6, 2026
    fdc1966
  6. added 2 commits that reference this issue on Oct 27, 2026
    60103e5
    7c4279c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:architectureArchitecture and code structure changesarea:inferenceGeneration, sampling, decoding (incl. speculative, DRY)priority:mediumMedium prioritystatus:doneCompletedtype:enhancementNew features, capabilities, or significant additions

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions