Skip to main content

synaps_cli/runtime/openai/catalog/
nvidia.rs

1//! NVIDIA NIM `/models` parser, context inference, and reasoning inference.
2
3use serde::Deserialize;
4
5use super::{CatalogModel, CatalogProviderKind, CatalogSource, ReasoningSupport};
6
7#[derive(Debug, Deserialize)]
8struct NvidiaModelsResponse {
9    data: Vec<NvidiaModelItem>,
10}
11
12#[derive(Debug, Deserialize)]
13struct NvidiaModelItem {
14    id: String,
15    #[serde(default)]
16    owned_by: Option<String>,
17}
18
19fn infer_nvidia_context_tokens(model_id: &str) -> Option<u64> {
20    let id = model_id.to_ascii_lowercase();
21    if id.contains("kimi-k2-thinking") { Some(256_000) }
22    else if id.contains("nemotron-ultra")
23        || id.contains("nemotron-super")
24        || id.contains("qwen3-next")
25        || id.contains("deepseek-v3.1")
26        || id.contains("llama-3.1-405b")
27        || id.contains("llama-3.2-90b-vision")
28        || id.contains("mistral-large-2")
29    { Some(128_000) }
30    else { None }
31}
32
33pub fn infer_nvidia_reasoning(model_id: &str) -> ReasoningSupport {
34    let id = model_id.to_ascii_lowercase();
35    if id.contains("thinking")
36        || id.contains("cosmos-reason")
37        || id.contains("nemotron-ultra")
38        || id.contains("nemotron-super")
39        || id.contains("mistral-nemotron")
40        || id.contains("magistral")
41        || id.contains("deepseek-v4")
42        || id.contains("kimi")
43        || id.contains("reasoning")
44    {
45        ReasoningSupport::NvidiaInlineThinking
46    } else {
47        ReasoningSupport::None
48    }
49}
50
51pub fn parse_nvidia_catalog_models(body: &str) -> Result<Vec<CatalogModel>, serde_json::Error> {
52    let resp: NvidiaModelsResponse = serde_json::from_str(body)?;
53    let mut seen = std::collections::BTreeSet::new();
54    Ok(resp
55        .data
56        .into_iter()
57        .filter_map(|item| {
58            let id = item.id;
59            if id.trim().is_empty() || !seen.insert(id.clone()) {
60                return None;
61            }
62            let mut m = CatalogModel::new("nvidia", "NVIDIA NIM", id)?;
63            m.provider_kind = CatalogProviderKind::NvidiaNim;
64            m.label = item.owned_by.as_ref().map(|owner| format!("{} — {}", m.id, owner));
65            m.context_tokens = infer_nvidia_context_tokens(&m.id);
66            m.reasoning = infer_nvidia_reasoning(&m.id);
67            m.source = if m.context_tokens.is_some() || m.reasoning != ReasoningSupport::None {
68                CatalogSource::Inferred
69            } else {
70                CatalogSource::Live
71            };
72            Some(m)
73        })
74        .collect())
75}