fix(vertex): prepend mandatory google/ publisher prefix to bare model names - #56809
fix(vertex): prepend mandatory google/ publisher prefix to bare model names#56809tangtaizong666 wants to merge 2 commits into
Conversation
Related Vertex normalization cluster: the former duplicate anchor #56806 is now closed unmerged, while current main still lacks a |
6660e6d to
56e1144
Compare
|
Acknowledged — overlap with #56806 is disclosed in the PR body (opened while my change was mid-test-run), including a behavior comparison table. The two deltas vs #56806: (1) bare names without a detectable Google vendor still get the mandatory |
56e1144 to
aaed31a
Compare
|
Thanks for the focused Vertex fix. Current main still lacks a The preservation of explicit publisher-qualified IDs and repair of aliases rely on the existing This is an automated hermes-sweeper review. |
… names
Vertex AI's OpenAI-compatible endpoint requires the model field in
<publisher>/<model> form and rejects bare names like gemini-3.1-flash-lite
with HTTP 400 INVALID_ARGUMENT ("Malformed publisher model").
normalize_model_for_provider() had no vertex branch, so bare names fell
through the as-is fallback and reached the API unprefixed.
Add a vertex branch: bare names gain the google/ publisher prefix;
explicit publisher prefixes (google/, anthropic/, meta/, ...) pass
through unchanged because Vertex hosts non-Google publishers too; a
matching vertex/ provider prefix copied from config is repaired to the
google/ publisher form.
Fixes NousResearch#56778
cd5621f to
099a032
Compare
What does this PR do?
Fixes the native Vertex AI provider (
--provider vertex) failing every request withHTTP 400 INVALID_ARGUMENT("Malformed publisher model") when the user supplies a standard bare model name such asgemini-3.1-flash-lite.Vertex AI's OpenAI-compatible endpoint requires the
modelfield in the mandatory<publisher>/<model>form (e.g.google/gemini-3.1-flash-lite).normalize_model_for_provider()inhermes_cli/model_normalize.pyhad novertexbranch, so bare names fell straight through the "pass through as-is" fallback and reached the API unprefixed. (The original Vertex feature PR #16010 — which contained normalization — was closed unmerged; the provider that landed as a plugin never picked up the prefix injection.)The new
vertexbranch applies these rules:gemini-3.1-flash-lite) → prepend thegoogle/publisher prefix.google/…,anthropic/…,meta/…,mistralai/…) → pass through unchanged. This deliberately deviates from the snippet suggested in the issue, which rewrote anyvendor/modeltogoogle/model— Vertex hosts non-Google publishers, so an explicit publisher is authoritative and must survive.vertex/gemini-3.5-flash,google-vertex/…— the aggregator-style form users copy into config.yaml) → repaired to thegoogle/publisher form, consistent with how other direct providers repairprovider/prefixes.Dots in model IDs are preserved (Vertex model IDs use them, e.g.
gemini-2.5-flash), and provider aliases (google-vertex,vertex-ai,gcp-vertex,vertexai) resolve to the same behavior.google/is never mistaken for a provider prefix because thegooglealias canonicalizes to thegeminiprovider, notvertex.Relationship to #56805 and #56806
Both opened while this change was going through its test run — flagging the overlap up front and deferring to maintainers on which to take. The behavioral differences are material, not cosmetic:
vertex)gemini-3.1-flash-lite(the issue)google/gemini-3.1-flash-lite✓google/gemini-3.1-flash-lite✓google/gemini-3.1-flash-lite✓anthropic/claude-sonnet-4.6google/anthropic/claude-sonnet-4.6— double prefix, malformedmeta/llama-3.3-70b-instruct-maas(Vertex MaaS)google/meta/…— malformedvertex/gemini-3.5-flash(copied into config)google/gemini-3.5-flash✓vertexisn't a Vertex publisher, still HTTP 400google/gemini-3.5-flash✓google/<name>google/<name>(On the last row: the endpoint's
<publisher>/<model>form is mandatory, so passing a bare name through can never succeed; defaulting togoogle/matches the provider's documented scope, "Gemini models via Google Cloud".)Related Issue
Fixes #56778
Type of Change
Changes Made
hermes_cli/model_normalize.py— newvertexbranch innormalize_model_for_provider()(strip a matchingvertex/provider prefix, keep any remaining explicitpublisher/, otherwise prependgoogle/); module docstring and function doctest examples updated.tests/hermes_cli/test_model_normalize.py— newTestIssue56778VertexPublisherPrefixregression class (12 cases: bare-name prefixing,google/pass-through, non-Google publisher preservation,vertex/-prefix repair, alias handling, dot preservation, empty input).scripts/release.py— added my commit email toAUTHOR_MAP, as required by the contributor-attribution CI check for first-time commit emails.How to Test
pytest tests/hermes_cli/test_model_normalize.py -q— the 12 newTestIssue56778VertexPublisherPrefixcases fail onmain(bare names pass through unprefixed) and pass with this change; the pre-existing 86 cases stay green.scripts/run_tests.sh tests/hermes_cli/test_model_normalize.py tests/hermes_cli/test_vertex_provider.py tests/agent/test_vertex_adapter.py(CI-equivalent per-file isolation) — 125/125 pass.ruff check .clean;tyreports no new diagnostics.hermes chat -q "echo" --provider vertex --model gemini-3.1-flash-lite(with GCP ADC configured) — previously died on the first turn withHTTP 400 "Malformed publisher model ('model': 'gemini-3.1-flash-lite')"; the request now goes out asgoogle/gemini-3.1-flash-lite, the form the issue reporter verified works.--model google/gemini-3.1-flash-litestill passes through untouched.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/A (no config keys changed)CONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/A (no architecture change)Screenshots / Logs
Normalization through the real path (
normalize_provider→normalize_model_for_provider), before vs. after: