fix(cli): report the auto-detected context length when a custom provider is saved without one
Leaving the context-length prompt blank in the custom-endpoint wizard said "will auto-detect" and then went silent, so users could not tell whether their endpoint runs on a detected window or the runtime's default fallback (which shapes compression and prompt-cache behaviour). After the save prompt, run the same resolver the runtime uses (with the endpoint's URL and key) and print either "auto-detected N tokens" or "not detected — using the default N tokens". Feedback only: the probe result is not persisted, and a failing probe never blocks the save. Fixes #2513. Approach from PR #2522 (@ygd58) and PR #85499 (@Luna161), both written against the pre-decomposition wizard module. Co-authored-by: Luna161 <268031236+Luna161@users.noreply.github.com>
This commit is contained in:
@@ -30,6 +30,28 @@ def _parse_context_length(text: str):
|
|||||||
return value if value > 0 else None
|
return value if value > 0 else None
|
||||||
|
|
||||||
|
|
||||||
|
def _report_context_length_detection(model_name: str, base_url: str, api_key: str) -> None:
|
||||||
|
"""Tell the user what the auto-detect resolver found for *model_name* at *base_url* (#2513).
|
||||||
|
|
||||||
|
The runtime resolver (``get_model_context_length``) probes /models, local servers and the
|
||||||
|
catalogs, then falls back to ``DEFAULT_FALLBACK_CONTEXT``; without this line a blank
|
||||||
|
context-length prompt gave no hint whether the saved endpoint runs on a detected value or
|
||||||
|
the silent default that shapes compression and cache windows. Feedback only — the value
|
||||||
|
is NOT written to config, which would freeze a probe result into a permanent override.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from agent.model_metadata import DEFAULT_FALLBACK_CONTEXT, get_model_context_length
|
||||||
|
from hermes_cli.banner import _format_context_length
|
||||||
|
detected = get_model_context_length(model_name, base_url=base_url, api_key=api_key or "")
|
||||||
|
except Exception: # a failing probe must never block the save
|
||||||
|
return
|
||||||
|
if detected and detected != DEFAULT_FALLBACK_CONTEXT:
|
||||||
|
print(f" Context length auto-detected: {_format_context_length(detected)} tokens")
|
||||||
|
else:
|
||||||
|
print(f" Context length: not detected — using the default {_format_context_length(DEFAULT_FALLBACK_CONTEXT)} tokens "
|
||||||
|
f"(set model.context_length in config.yaml to override)")
|
||||||
|
|
||||||
|
|
||||||
def _probe_custom_endpoint(effective_key: str, effective_url: str) -> tuple[dict, str]:
|
def _probe_custom_endpoint(effective_key: str, effective_url: str) -> tuple[dict, str]:
|
||||||
"""Verify a custom endpoint via ``probe_api_models`` and report; returns
|
"""Verify a custom endpoint via ``probe_api_models`` and report; returns
|
||||||
``(probe, effective_url)`` where the URL may be the working fallback base."""
|
``(probe, effective_url)`` where the URL may be the working fallback base."""
|
||||||
@@ -136,6 +158,8 @@ def _model_flow_custom(config):
|
|||||||
print("\nCancelled.")
|
print("\nCancelled.")
|
||||||
return
|
return
|
||||||
context_length = _parse_context_length(context_length_str)
|
context_length = _parse_context_length(context_length_str)
|
||||||
|
if context_length is None and model_name:
|
||||||
|
_report_context_length_detection(model_name, effective_url, effective_key)
|
||||||
|
|
||||||
# The key goes to .env and config.yaml only references it. Keyed on host:port
|
# The key goes to .env and config.yaml only references it. Keyed on host:port
|
||||||
# so two servers on one machine keep separate credentials.
|
# so two servers on one machine keep separate credentials.
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
"""#2513: a blank context-length prompt in the custom-endpoint wizard tells the user whether the
|
||||||
|
runtime resolver detected a value or will run on the silent default."""
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from hermes_cli import model_setup_flows_custom as flows
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("resolved, expect", [
|
||||||
|
(200_000, "auto-detected"),
|
||||||
|
(None, "using the default"),
|
||||||
|
])
|
||||||
|
def test_blank_context_length_reports_detection_outcome(capsys, resolved, expect):
|
||||||
|
from agent.model_metadata import DEFAULT_FALLBACK_CONTEXT
|
||||||
|
with patch("agent.model_metadata.get_model_context_length",
|
||||||
|
return_value=resolved if resolved is not None else DEFAULT_FALLBACK_CONTEXT) as probe:
|
||||||
|
flows._report_context_length_detection("some-model", "http://localhost:8000/v1", "k")
|
||||||
|
probe.assert_called_once_with("some-model", base_url="http://localhost:8000/v1", api_key="k")
|
||||||
|
assert expect in capsys.readouterr().out
|
||||||
|
|
||||||
|
|
||||||
|
def test_probe_failure_never_blocks_the_save(capsys):
|
||||||
|
with patch("agent.model_metadata.get_model_context_length", side_effect=RuntimeError("boom")):
|
||||||
|
flows._report_context_length_detection("some-model", "http://x/v1", "")
|
||||||
|
assert capsys.readouterr().out == ""
|
||||||
Reference in New Issue
Block a user