mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-24 16:54:43 +00:00
feat(image_routing): accept vision alias for custom provider models
Extend the existing candidate-name resolver in _supports_vision_override to accept 'vision' as an alias for 'supports_vision' on per-model config, for both the providers.<name>.models dict and the legacy list-style custom_providers form. Per review feedback on #31912: this extends the current resolver rather than replacing its candidate-name logic. Named custom providers resolve to the runtime value provider='custom' while the config keeps the user-declared name under model.provider; that lookup path is preserved. Adds regression tests covering model.provider=my-vllm with runtime provider='custom' for both config shapes.
This commit is contained in:
parent
51083d2edc
commit
6bd02ae1a6
2 changed files with 106 additions and 2 deletions
|
|
@ -194,6 +194,10 @@ def _supports_vision_override(
|
|||
and/or the user-declared name under ``model.provider``; all are
|
||||
tried. For ``custom:<name>`` syntax, the stripped ``<name>`` is also
|
||||
tried as a provider key.)
|
||||
2b. ``custom_providers`` (legacy list form) ``.models.<model>``
|
||||
|
||||
Under (2) and (2b), the per-model capability key may be written as
|
||||
either ``supports_vision`` or the shorter ``vision`` alias; both work.
|
||||
|
||||
Returns None when no override is set, so the caller falls through to
|
||||
models.dev. Returns False explicitly only when the user wrote a
|
||||
|
|
@ -234,7 +238,9 @@ def _supports_vision_override(
|
|||
models_cfg: Dict[str, Any] = models_raw if isinstance(models_raw, dict) else {}
|
||||
per_model_raw = models_cfg.get(model)
|
||||
per_model: Dict[str, Any] = per_model_raw if isinstance(per_model_raw, dict) else {}
|
||||
coerced = _coerce_capability_bool(per_model.get("supports_vision"))
|
||||
coerced = _coerce_capability_bool(
|
||||
per_model.get("supports_vision", per_model.get("vision"))
|
||||
)
|
||||
if coerced is not None:
|
||||
return coerced
|
||||
|
||||
|
|
@ -258,7 +264,9 @@ def _supports_vision_override(
|
|||
models_cfg = models_raw if isinstance(models_raw, dict) else {}
|
||||
per_model_raw = models_cfg.get(model)
|
||||
per_model = per_model_raw if isinstance(per_model_raw, dict) else {}
|
||||
coerced = _coerce_capability_bool(per_model.get("supports_vision"))
|
||||
coerced = _coerce_capability_bool(
|
||||
per_model.get("supports_vision", per_model.get("vision"))
|
||||
)
|
||||
if coerced is not None:
|
||||
return coerced
|
||||
|
||||
|
|
|
|||
|
|
@ -874,3 +874,99 @@ class TestFormatCompatibility:
|
|||
img_path.write_bytes(b'<svg xmlns="http://www.w3.org/2000/svg" width="4" height="4"/>')
|
||||
url = _file_to_data_url(img_path)
|
||||
assert url is None
|
||||
|
||||
|
||||
# ─── vision alias for custom providers ──────────────────────────────────────
|
||||
|
||||
|
||||
class TestCustomProviderVisionAlias:
|
||||
"""`vision: true` should work as an alias for `supports_vision: true`.
|
||||
|
||||
Covers both config shapes that host named custom providers:
|
||||
* the ``providers.<name>.models`` dict, and
|
||||
* the legacy list-style ``custom_providers`` entries.
|
||||
|
||||
Regression for the review of PR #31912: named custom providers resolve
|
||||
to the runtime value ``provider="custom"`` while the config keeps the
|
||||
user-declared name under ``model.provider``. The existing candidate-name
|
||||
resolver must be *extended* to accept the ``vision`` alias, not replaced.
|
||||
"""
|
||||
|
||||
def test_providers_dict_vision_alias_true(self):
|
||||
cfg = {
|
||||
"providers": {
|
||||
"my-vllm": {"models": {"llava-v1.6": {"vision": True}}}
|
||||
}
|
||||
}
|
||||
assert _supports_vision_override(cfg, "my-vllm", "llava-v1.6") is True
|
||||
|
||||
def test_providers_dict_vision_alias_false(self):
|
||||
cfg = {
|
||||
"providers": {
|
||||
"my-vllm": {"models": {"llama-3": {"vision": False}}}
|
||||
}
|
||||
}
|
||||
assert _supports_vision_override(cfg, "my-vllm", "llama-3") is False
|
||||
|
||||
def test_supports_vision_wins_over_vision_alias(self):
|
||||
"""When both keys are present, the canonical key takes priority."""
|
||||
cfg = {
|
||||
"providers": {
|
||||
"my-vllm": {
|
||||
"models": {
|
||||
"m": {"supports_vision": True, "vision": False}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert _supports_vision_override(cfg, "my-vllm", "m") is True
|
||||
|
||||
def test_named_custom_provider_bare_custom_runtime_vision_alias(self):
|
||||
"""Teknium's requested regression case.
|
||||
|
||||
A named custom provider (``model.provider: my-vllm``) is rewritten to
|
||||
the runtime value ``provider="custom"`` by
|
||||
``hermes_cli/runtime_provider.py``. The resolver must still match the
|
||||
``my-vllm`` entry via the ``model.provider`` candidate and honour the
|
||||
``vision`` alias.
|
||||
"""
|
||||
cfg = {
|
||||
"model": {"provider": "my-vllm"},
|
||||
"providers": {
|
||||
"my-vllm": {"models": {"llava-v1.6": {"vision": True}}}
|
||||
},
|
||||
}
|
||||
# Runtime provider is the bare normalized value "custom".
|
||||
assert _supports_vision_override(cfg, "custom", "llava-v1.6") is True
|
||||
assert decide_image_input_mode("custom", "llava-v1.6", cfg) == "native"
|
||||
|
||||
def test_custom_providers_list_bare_custom_runtime_vision_alias(self):
|
||||
"""Same regression, but the provider lives in the legacy list form."""
|
||||
cfg = {
|
||||
"model": {"provider": "my-vllm"},
|
||||
"custom_providers": [
|
||||
{
|
||||
"name": "my-vllm",
|
||||
"models": {"llava-v1.6": {"vision": True}},
|
||||
}
|
||||
],
|
||||
}
|
||||
assert _supports_vision_override(cfg, "custom", "llava-v1.6") is True
|
||||
assert decide_image_input_mode("custom", "llava-v1.6", cfg) == "native"
|
||||
|
||||
def test_custom_providers_list_vision_alias_false(self):
|
||||
cfg = {
|
||||
"model": {"provider": "my-vllm"},
|
||||
"custom_providers": [
|
||||
{"name": "my-vllm", "models": {"llama-3": {"vision": False}}}
|
||||
],
|
||||
}
|
||||
assert _supports_vision_override(cfg, "custom", "llama-3") is False
|
||||
|
||||
def test_vision_alias_none_when_model_absent(self):
|
||||
cfg = {
|
||||
"custom_providers": [
|
||||
{"name": "my-vllm", "models": {"llava": {"vision": True}}}
|
||||
]
|
||||
}
|
||||
assert _supports_vision_override(cfg, "custom:my-vllm", "other") is None
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue