Instructions to use HelloSun/Nemotron74ba9 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use HelloSun/Nemotron74ba9 with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf HelloSun/Nemotron74ba9 # Run inference directly in the terminal: llama cli -hf HelloSun/Nemotron74ba9
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf HelloSun/Nemotron74ba9 # Run inference directly in the terminal: llama cli -hf HelloSun/Nemotron74ba9
Build from source code
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-app # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama serve -hf HelloSun/Nemotron74ba9 # Run inference directly in the terminal: ./build/bin/llama cli -hf HelloSun/Nemotron74ba9
Use Docker
docker model run hf.co/HelloSun/Nemotron74ba9
- Llama new
- LM Studio
- Jan
- Ollama
How to use HelloSun/Nemotron74ba9 with Ollama:
ollama run hf.co/HelloSun/Nemotron74ba9
- Unsloth Desktop
- Pi
How to use HelloSun/Nemotron74ba9 with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf HelloSun/Nemotron74ba9
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "HelloSun/Nemotron74ba9" } ] } } }Run Pi
# Start Pi in your project directory: pi
- Docker Model Runner
How to use HelloSun/Nemotron74ba9 with Docker Model Runner:
docker model run hf.co/HelloSun/Nemotron74ba9
- Lemonade
How to use HelloSun/Nemotron74ba9 with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull HelloSun/Nemotron74ba9
Run and chat with the model
lemonade run user.Nemotron74ba9-{{QUANT_TAG}}List all available models
lemonade list
- Hermes Agent
How to use HelloSun/Nemotron74ba9 with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf HelloSun/Nemotron74ba9
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default HelloSun/Nemotron74ba9
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use HelloSun/Nemotron74ba9 with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf HelloSun/Nemotron74ba9
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "HelloSun/Nemotron74ba9" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
experiment E1: fp16 prefill GEMM (pp512 40.0 -> 57.0 t/s)
Browse files
patches/0002-nvfp4-f16-prefill.patch
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
--- a/ggml/src/ggml-cpu/ggml-cpu.c
|
| 2 |
+
+++ b/ggml/src/ggml-cpu/ggml-cpu.c
|
| 3 |
+
@@ -77,6 +77,56 @@
|
| 4 |
+
#define UNUSED GGML_UNUSED
|
| 5 |
+
#define SWAP(x, y, T) do { T SWAP = x; (x) = y; (y) = SWAP; } while (0)
|
| 6 |
+
|
| 7 |
+
+#if GGML_USE_LLAMAFILE && defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512VL__) && defined(__AVX512VNNI__)
|
| 8 |
+
+#include <pthread.h>
|
| 9 |
+
+// Lazily dequantized fp16 shadow of the NVFP4 weights, used for prompt processing only. The dequantization is
|
| 10 |
+
+// exact (see ggml_nvfp4_to_fp16_row), so logits are unchanged; decode keeps using the packed 4-bit weights.
|
| 11 |
+
+#define GGML_NVFP4_SHADOW_MAX 512
|
| 12 |
+
+static pthread_mutex_t g_nvfp4_shadow_mu = PTHREAD_MUTEX_INITIALIZER;
|
| 13 |
+
+static struct {
|
| 14 |
+
+ const void * src;
|
| 15 |
+
+ void * data;
|
| 16 |
+
+} g_nvfp4_shadow[GGML_NVFP4_SHADOW_MAX];
|
| 17 |
+
+static int g_nvfp4_shadow_n = 0;
|
| 18 |
+
+
|
| 19 |
+
+static void * ggml_nvfp4_shadow_get(const void * src, int64_t K, int64_t M, size_t bx) {
|
| 20 |
+
+ pthread_mutex_lock(&g_nvfp4_shadow_mu);
|
| 21 |
+
+ void * data = NULL;
|
| 22 |
+
+ for (int i = 0; i < g_nvfp4_shadow_n; ++i) {
|
| 23 |
+
+ if (g_nvfp4_shadow[i].src == src) { data = g_nvfp4_shadow[i].data; break; }
|
| 24 |
+
+ }
|
| 25 |
+
+ if (data == NULL && g_nvfp4_shadow_n < GGML_NVFP4_SHADOW_MAX) {
|
| 26 |
+
+ data = aligned_alloc(64, (size_t) K * M * sizeof(ggml_fp16_t));
|
| 27 |
+
+ if (data != NULL) {
|
| 28 |
+
+ for (int64_t r = 0; r < M; ++r) {
|
| 29 |
+
+ ggml_nvfp4_to_fp16_row((const char *) src + r * bx,
|
| 30 |
+
+ (ggml_fp16_t *) data + r * K, K);
|
| 31 |
+
+ }
|
| 32 |
+
+ g_nvfp4_shadow[g_nvfp4_shadow_n].src = src;
|
| 33 |
+
+ g_nvfp4_shadow[g_nvfp4_shadow_n].data = data;
|
| 34 |
+
+ g_nvfp4_shadow_n++;
|
| 35 |
+
+ }
|
| 36 |
+
+ }
|
| 37 |
+
+ pthread_mutex_unlock(&g_nvfp4_shadow_mu);
|
| 38 |
+
+ return data;
|
| 39 |
+
+}
|
| 40 |
+
+
|
| 41 |
+
+// Scratch buffer holding the fp16 activations for the fp16 GEMM path. Reused between ops; the graph executes
|
| 42 |
+
+// one matmul at a time, so a single buffer is enough.
|
| 43 |
+
+static void * g_nvfp4_act = NULL;
|
| 44 |
+
+static size_t g_nvfp4_act_sz = 0;
|
| 45 |
+
+
|
| 46 |
+
+static void * ggml_nvfp4_act_get(size_t need) {
|
| 47 |
+
+ if (need > g_nvfp4_act_sz) {
|
| 48 |
+
+ free(g_nvfp4_act);
|
| 49 |
+
+ need = (need + 63) & ~(size_t) 63;
|
| 50 |
+
+ g_nvfp4_act = aligned_alloc(64, need);
|
| 51 |
+
+ g_nvfp4_act_sz = g_nvfp4_act ? need : 0;
|
| 52 |
+
+ }
|
| 53 |
+
+ return g_nvfp4_act;
|
| 54 |
+
+}
|
| 55 |
+
+#endif
|
| 56 |
+
+
|
| 57 |
+
// precomputed f32 table for f16 (256 KB) (simd-mappings.h)
|
| 58 |
+
float ggml_table_f32_f16[1 << 16];
|
| 59 |
+
|
| 60 |
+
@@ -1325,6 +1375,49 @@
|
| 61 |
+
UseGgmlGemm1:;
|
| 62 |
+
#endif
|
| 63 |
+
|
| 64 |
+
+#if GGML_USE_LLAMAFILE && defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512VL__) && defined(__AVX512VNNI__)
|
| 65 |
+
+ // Prompt processing of the NVFP4 projections through an exact fp16 shadow + fp16 GEMM. This replaces the
|
| 66 |
+
+ // per-column 4-bit dot products, which re-read and re-decode the weights for every pair of tokens.
|
| 67 |
+
+ if (!params->use_ref && src0->type == GGML_TYPE_NVFP4 && src1->type == GGML_TYPE_F32 &&
|
| 68 |
+
+ ggml_is_contiguous(src1) &&
|
| 69 |
+
+ ne02 == 1 && ne03 == 1 && ne12 == 1 && ne13 == 1 &&
|
| 70 |
+
+ ne11 >= 8 && ne00 % QK_NVFP4 == 0 &&
|
| 71 |
+
+ dst->type == GGML_TYPE_F32 && nb0 == (int64_t) sizeof(float) &&
|
| 72 |
+
+ nb1 == (int64_t) ne0 * (int64_t) sizeof(float) &&
|
| 73 |
+
+ nb11 == (int64_t) ne00 * (int64_t) sizeof(float) &&
|
| 74 |
+
+ (params->nth == 1 || params->threadpool != NULL)) {
|
| 75 |
+
+ void * A = NULL;
|
| 76 |
+
+ void * act16 = NULL;
|
| 77 |
+
+ if (ith == 0) {
|
| 78 |
+
+ A = ggml_nvfp4_shadow_get(src0->data, ne00, ne01, nb01);
|
| 79 |
+
+ act16 = ggml_nvfp4_act_get((size_t) ne00 * ne11 * sizeof(ggml_fp16_t));
|
| 80 |
+
+ }
|
| 81 |
+
+ if (params->nth > 1) {
|
| 82 |
+
+ ggml_barrier(params->threadpool);
|
| 83 |
+
+ }
|
| 84 |
+
+ if (ith != 0) {
|
| 85 |
+
+ A = ggml_nvfp4_shadow_get(src0->data, ne00, ne01, nb01);
|
| 86 |
+
+ act16 = g_nvfp4_act;
|
| 87 |
+
+ }
|
| 88 |
+
+ if (A != NULL && act16 != NULL) {
|
| 89 |
+
+ const int64_t c0 = (ne11 * ith) / nth;
|
| 90 |
+
+ const int64_t c1 = (ne11 * (ith + 1)) / nth;
|
| 91 |
+
+ for (int64_t c = c0; c < c1; ++c) {
|
| 92 |
+
+ ggml_fp32_to_fp16_row((const float *) ((const char *) src1->data + c * nb11),
|
| 93 |
+
+ (ggml_fp16_t *) act16 + c * ne00, ne00);
|
| 94 |
+
+ }
|
| 95 |
+
+ if (params->nth > 1) {
|
| 96 |
+
+ ggml_barrier(params->threadpool);
|
| 97 |
+
+ }
|
| 98 |
+
+ if (llamafile_sgemm(params, ne01, ne11, ne00, A, ne00,
|
| 99 |
+
+ act16, ne00, dst->data, ne0,
|
| 100 |
+
+ GGML_TYPE_F16, GGML_TYPE_F16, GGML_TYPE_F32)) {
|
| 101 |
+
+ return;
|
| 102 |
+
+ }
|
| 103 |
+
+ }
|
| 104 |
+
+ }
|
| 105 |
+
+#endif
|
| 106 |
+
+
|
| 107 |
+
if (src1->type != vec_dot_type) {
|
| 108 |
+
char * wdata = params->wdata;
|
| 109 |
+
|
| 110 |
+
--- a/ggml/src/ggml-cpu/arch/x86/quants.c
|
| 111 |
+
+++ b/ggml/src/ggml-cpu/arch/x86/quants.c
|
| 112 |
+
@@ -1142,6 +1142,46 @@
|
| 113 |
+
}
|
| 114 |
+
#endif
|
| 115 |
+
|
| 116 |
+
+// Dequantize one NVFP4 row into fp16. The result is exact: E2M1 magnitudes times the UE4M3 sub-block
|
| 117 |
+
+// scales fit in fp16, so prefill can run an ordinary fp16 GEMM instead of the 4-bit dot product.
|
| 118 |
+
+void ggml_nvfp4_to_fp16_row(const void * GGML_RESTRICT vx, ggml_fp16_t * GGML_RESTRICT y, int64_t k) {
|
| 119 |
+
+ const block_nvfp4 * GGML_RESTRICT x = (const block_nvfp4 *) vx;
|
| 120 |
+
+ const int nb = (int) (k / QK_NVFP4);
|
| 121 |
+
+#if defined(__AVX512F__) && defined(__AVX512BW__) && defined(__AVX512VL__)
|
| 122 |
+
+ const __m512 tbl = _mm512_setr_ps(
|
| 123 |
+
+ (float) kvalues_fp4[ 0], (float) kvalues_fp4[ 1], (float) kvalues_fp4[ 2], (float) kvalues_fp4[ 3],
|
| 124 |
+
+ (float) kvalues_fp4[ 4], (float) kvalues_fp4[ 5], (float) kvalues_fp4[ 6], (float) kvalues_fp4[ 7],
|
| 125 |
+
+ (float) kvalues_fp4[ 8], (float) kvalues_fp4[ 9], (float) kvalues_fp4[10], (float) kvalues_fp4[11],
|
| 126 |
+
+ (float) kvalues_fp4[12], (float) kvalues_fp4[13], (float) kvalues_fp4[14], (float) kvalues_fp4[15]);
|
| 127 |
+
+
|
| 128 |
+
+ for (int ib = 0; ib < nb; ++ib) {
|
| 129 |
+
+ const __m512i nib = nvfp4_nibbles_512(&x[ib]);
|
| 130 |
+
+ const __m128 sc4 = nvfp4_scale4_128(&x[ib]);
|
| 131 |
+
+ for (int s = 0; s < 4; ++s) {
|
| 132 |
+
+ const __m128i bytes = _mm512_extracti32x4_epi32(nib, s);
|
| 133 |
+
+ const __m512i idx = _mm512_cvtepu8_epi32(bytes);
|
| 134 |
+
+ __m512 v = _mm512_permutexvar_ps(idx, tbl);
|
| 135 |
+
+ const float sc = _mm_cvtss_f32(_mm_shuffle_ps(sc4, sc4, _MM_SHUFFLE(s, s, s, s)));
|
| 136 |
+
+ v = _mm512_mul_ps(v, _mm512_set1_ps(sc));
|
| 137 |
+
+ const __m256i h = _mm512_cvtps_ph(v, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC);
|
| 138 |
+
+ _mm256_storeu_si256((__m256i *) (y + (int64_t) ib*QK_NVFP4 + s*16), h);
|
| 139 |
+
+ }
|
| 140 |
+
+ }
|
| 141 |
+
+#else
|
| 142 |
+
+ for (int ib = 0; ib < nb; ++ib) {
|
| 143 |
+
+ for (int s = 0; s < 4; ++s) {
|
| 144 |
+
+ const float d = ggml_ue4m3_to_fp32(x[ib].d[s]);
|
| 145 |
+
+ for (int j = 0; j < 8; ++j) {
|
| 146 |
+
+ const uint8_t q = x[ib].qs[s*8 + j];
|
| 147 |
+
+ const int64_t base = (int64_t) ib*QK_NVFP4 + s*16;
|
| 148 |
+
+ y[base + j] = ggml_fp32_to_fp16((float) kvalues_fp4[q & 0x0F] * d);
|
| 149 |
+
+ y[base + j + 8] = ggml_fp32_to_fp16((float) kvalues_fp4[q >> 4] * d);
|
| 150 |
+
+ }
|
| 151 |
+
+ }
|
| 152 |
+
+ }
|
| 153 |
+
+#endif
|
| 154 |
+
+}
|
| 155 |
+
+
|
| 156 |
+
void ggml_vec_dot_nvfp4_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc) {
|
| 157 |
+
assert(nrc == 1 || nrc == 2);
|
| 158 |
+
assert(n % QK_NVFP4 == 0);
|
| 159 |
+
--- a/ggml/src/ggml-cpu/quants.h
|
| 160 |
+
+++ b/ggml/src/ggml-cpu/quants.h
|
| 161 |
+
@@ -48,6 +48,7 @@
|
| 162 |
+
|
| 163 |
+
void ggml_vec_dot_mxfp4_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);
|
| 164 |
+
void ggml_vec_dot_nvfp4_q8_0(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);
|
| 165 |
+
+void ggml_nvfp4_to_fp16_row(const void * GGML_RESTRICT vx, ggml_fp16_t * GGML_RESTRICT y, int64_t k);
|
| 166 |
+
|
| 167 |
+
void ggml_vec_dot_q2_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);
|
| 168 |
+
void ggml_vec_dot_q3_K_q8_K(int n, float * GGML_RESTRICT s, size_t bs, const void * GGML_RESTRICT vx, size_t bx, const void * GGML_RESTRICT vy, size_t by, int nrc);
|