feat(studio): infinite scroll for recommended models list (#4414)
* feat(studio): infinite scroll for recommended models list The model selector showed a hard cap of 4 GGUFs + 4 safetensors in the Recommended section. Users who wanted to browse more had to search manually on Hugging Face. Backend: increase the default model pool from 8+8 to 40+40 (the HF fetch already pulls 80, so no extra network cost). Frontend: replace the static 4+4 cap with on-demand lazy loading. A page counter tracks how many groups of 4 to show per category. An IntersectionObserver on a sentinel div at the bottom of the list increments the page when the user scrolls down. Models are interleaved in groups of 4 GGUFs then 4 hub models per page for a balanced view. Key implementation details: - Callback ref for the sentinel so the observer attaches reliably on first popover open (useRef would miss the initial mount) - Observer disconnects after each fire and re-attaches via useEffect with a 100ms layout delay to prevent runaway page loading - VRAM info fetched incrementally via useRecommendedModelVram on the visible slice only - recommendedSet uses visible IDs so HF search dedup stays correct * refactor: address review feedback on recommended infinite scroll - Simplify visibleRecommendedIds: use findIndex to locate the GGUF/hub split point instead of re-filtering the entire array each time. recommendedIds is already sorted GGUF-first, so a single slice is enough. - Fix VRAM refetch churn: pass the full recommendedIds (stable across page increments) to useRecommendedModelVram instead of the growing visibleRecommendedIds slice. The hook derives its stableKey from the sorted+joined input, so passing the same pool on every page avoids redundant HF modelInfo requests.
This commit is contained in:
parent
67d3519cab
commit
65acefd2a6
2 changed files with 70 additions and 14 deletions
|
|
@ -130,17 +130,17 @@ class InferenceOrchestrator:
|
|||
)
|
||||
if resp.status_code == 200:
|
||||
models = resp.json()
|
||||
# Top 8 GGUFs (frontend deduplicates against downloaded,
|
||||
# so we fetch extra to always fill 4 slots)
|
||||
# Top 40 GGUFs - frontend pages through them on-demand via
|
||||
# infinite scroll, so we send a deep pool.
|
||||
gguf_ids = [
|
||||
m["id"] for m in models if m.get("id", "").upper().endswith("-GGUF")
|
||||
][:8]
|
||||
# Top 8 non-GGUF hub models
|
||||
][:40]
|
||||
# Top 40 non-GGUF hub models
|
||||
hub_ids = [
|
||||
m["id"]
|
||||
for m in models
|
||||
if not m.get("id", "").upper().endswith("-GGUF")
|
||||
][:8]
|
||||
][:40]
|
||||
if gguf_ids:
|
||||
self._top_gguf_cache = gguf_ids
|
||||
logger.info("Top GGUF models: %s", gguf_ids)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue