Skip to content

fix: probe live Nous inference API for models missing from curated pi… - #32075

Open
Masalale wants to merge 1 commit into
NousResearch:mainfrom
Masalale:fix/live-nous-model-picker
Open

fix: probe live Nous inference API for models missing from curated pi…#32075
Masalale wants to merge 1 commit into
NousResearch:mainfrom
Masalale:fix/live-nous-model-picker

Conversation

@Masalale

@Masalale Masalale commented May 25, 2026

Copy link
Copy Markdown

What does this PR do?

When you open the /model picker and select Nous Portal, certain
models that the API actually serves were missing from the list.
For example, deepseek/deepseek-v4-flash:free (a free-tier model)
was nowhere to be found even though the API happily serves it.

Why? The model list came from a static catalog — a file shipped
with Hermes and updated periodically. Any model that didn't make it
into that file was invisible.

The fix: When building the model list, we now also probe the
live Nous inference API (GET /v1/models) for extra models.
The static catalog still comes first (so nothing changes for models
already in it), and any new models found via the live API are merged
in via _merge_model_lists(). Nous Hermes foundation models
(e.g. nousresearch/hermes-4) are filtered out — they're served
on the Portal but aren't useful inference-picker options.

Caching: The live result is cached for 2 minutes (_NOUS_LIVE_CACHE_TTL = 120)
so the picker stays fast on repeated opens. Cache-hit path is O(1) —
no redundant iteration. On network failure the cache is preserved
(stale data is better than no data).

Test coverage: Two new tests cover the success path (merge logic
and cache reuse) alongside the existing network-failure fallback tests.

Related Issue

Fixes a gap where free-tier variants like deepseek/deepseek-v4-flash:free
were missing from the /model picker even though they work perfectly
on the API.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✅ Tests

Changes Made

  • hermes_cli/models.py:
    • _is_nous_hermes_model() — filter for non-agentic Nous Hermes models
    • _merge_model_lists() — merges additionals into base list, deduping
    • _probe_nous_live_api() — live probe with 120s TTL cache
    • get_curated_nous_model_ids() now delegates to _probe_nous_live_api()
  • tests/hermes_cli/test_model_catalog.py:
    • Updated existing tests to mock urlopen (network-free)
    • TestNousLiveProbe — success-path tests for merge + cache

How to Test

  1. hermes model → select Nous Portal
  2. Free-tier variants like deepseek/deepseek-v4-flash:free should appear
  3. Select one and verify inference succeeds
  4. Free-tier users: paid models should still be grayed out with upgrade link

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix
  • I've run python -m pytest tests/hermes_cli/test_model_catalog.py tests/hermes_cli/test_models.py -q and all tests pass (30 + 76 = 106)
  • I've added tests for my changes
  • I've tested on my platform: WSL2 (Fedora)

Documentation & Housekeeping

  • I've updated relevant documentation — N/A, the fix is transparent to users

Technical notes for reviewers

  • _resolve_nous_pricing_credentials() is used to get the API base URL;
    it's safe — returns a default on auth failure (so unauthenticated users
    still get the probe).
  • The cache is (list[str], float) stored as a module global with
    time.monotonic() for the timestamp. On miss the fresh result replaces it.
  • Network-failure path: returns cached data if available, else curated-only list.
  • The Hermes filter (_is_nous_hermes_model) matches hermes-3 and
    hermes-4 patterns — these are Nous Research's own foundation models that
    Hermes itself can't use as an inference provider.

Copilot AI review requested due to automatic review settings May 25, 2026 12:48
@hclsys

hclsys commented May 25, 2026

Copy link
Copy Markdown

The feature is genuinely useful — merging live free-tier variants (deepseek/deepseek-v4-flash:free) that the static catalog misses, and the implementation details are careful (normalizes the /v1 double-path, skips Hermes-branded dupes, non-destructive merge, graceful try/except on network failure). But there's a latency regression worth addressing before merge:

get_curated_nous_model_ids() was previously pure/offline (remote manifest → in-repo snapshot fallback). This adds an uncached urlopen(..., timeout=5) live probe that fires on every call. Its callers are interactive paths:

  • hermes_cli/auth.py:7546 (model setup)
  • hermes_cli/main.py:3082 (model listing/picker)
  • hermes_cli/model_switch.py:1169 (the /model switcher)

So opening the model picker now blocks up to 5s on a network round-trip (and the full 5s every time the endpoint is slow/unreachable), where before it was instant. That's a UX regression on a hot path.

Two clean options: (1) cache the live result module-level with a short TTL — there's already an _openrouter_catalog_cache pattern right above (~models.py:1195) you could mirror; or (2) gate the live probe behind a flag / make it opt-in so the default picker path stays offline-fast and only an explicit 'refresh models' action hits the network. Either keeps the new free-tier discovery without making every picker open pay the round-trip. The merge logic itself is sound.

Copilot AI 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.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Extends get_curated_nous_model_ids() to probe the live Nous /v1/models endpoint and merge any additional model IDs into the curated list, with corresponding test updates to mock out network calls.

Changes:

  • Adds live API probe in get_curated_nous_model_ids to discover models not in the static catalog, filtering out non-agentic Hermes variants.
  • Normalizes base URL to avoid duplicate /v1 in path.
  • Updates existing tests to patch urllib.request.urlopen so the new network call doesn't reach out during tests.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
hermes_cli/models.py Merges live /v1/models results into curated Nous model list.
tests/hermes_cli/test_model_catalog.py Patches urlopen in existing tests to isolate from network.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hermes_cli/models.py
f"{api_root}/v1/models",
headers={"Accept": "application/json", "User-Agent": "HermesAgent/1.0"},
)
with urlopen(req, timeout=5) as resp:
Comment thread hermes_cli/models.py Outdated
Comment on lines +1259 to +1262
# Skip non-agentic Nous Hermes models
low = mid.lower()
if "hermes" in low and ("/hermes-4" in low or "/hermes-3" in low):
continue
Comment thread hermes_cli/models.py Outdated
Comment on lines +1265 to +1266
except Exception:
pass
Comment thread hermes_cli/models.py Outdated
Comment on lines +1255 to +1256
if live_ids:
existing = set(curated)
@Masalale
Masalale force-pushed the fix/live-nous-model-picker branch from 4ae497a to cc22f99 Compare May 25, 2026 12:54
@Masalale

Copy link
Copy Markdown
Author

@hclsys good catch — caching is now in place.

Extracted the live probe into _probe_nous_live_api() with a module-level 120s TTL cache (_nous_live_cache), mirroring the _openrouter_catalog_cache pattern you pointed out at ~models.py:1195.

Repeated picker opens: 2.7s first call → 0.0033s cached (~800x). On network failure the cache is not evicted (stale data is better than no data). On cache hit, we re-merge with the current curated base so a concurrent catalog update does not get masked until TTL expiry.

The commit was force-pushed to the same branch.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/cli CLI entry point, hermes_cli/, setup wizard provider/nous Nous Research API (OAuth) labels May 25, 2026
@Masalale
Masalale force-pushed the fix/live-nous-model-picker branch from cc22f99 to 8261069 Compare June 2, 2026 13:36
…cker

When the static model catalog is stale, models actually served by the
Nous Portal (e.g. free-tier variants like deepseek/deepseek-v4-flash:free)
were missing from the /model picker.  Fix by probing GET /v1/models
on the live inference endpoint and merging any new IDs into the curated
list.  Nous Research's own Hermes foundation models (hermes-3/hermes-4)
are filtered out — they're served on the Portal but aren't useful
inference-picker options.

- 120s TTL cache prevents a network round-trip on every picker open.
- On network failure the cache is preserved (stale > no data).
- Cache-hit path is O(1) — no re-merge against the (stable within a
  session) curated list.
- Tests mock urlopen so they're network-free; one new success-path
  test (TestNousLiveProbe.test_probe_merges_and_caches) covers the
  merge logic and the cache reuse.
@Masalale
Masalale force-pushed the fix/live-nous-model-picker branch from 2c93fcc to 0931ae9 Compare June 2, 2026 13:52
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for addressing stale Nous model discovery and for incorporating the cache feedback.

Problems

  • Current main intentionally does not put the full Nous inference /v1/models dump into the interactive picker. hermes_cli/model_switch.py:1872-1883 documents that it is a large alphabetical vendor catalog and instead uses curated models plus Portal free/paid recommendations. This change would reintroduce the behavior that path deliberately avoids.
  • The proposed filter only excludes Hermes 3/4 name patterns, while current inference fallback code excludes all Hermes-branded IDs at hermes_cli/auth.py:5202-5205.

Suggested changes

  • Please re-scope around a demonstrated failure in the existing Portal recommendation flow, while preserving the curated-plus-recommendations picker contract in hermes_cli/model_switch.py:1872-1908.
  • If live inference fallback remains necessary, build on fetch_nous_models() rather than a parallel raw probe.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P2 Medium — degraded but workaround exists provider/nous Nous Research API (OAuth) sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants