close

DEV Community

xbill for Google Developer Experts

Posted on

Gemma4 DevOps In Action

Cutting costs 8.6x by shrinking hardware footprint

In the last entry I got Gemma-4's 128-expert MoE running on an inf2.24xlarge and signed off with a
cliffhanger: fitting it on a 2-core box "needs fp4 — a separate expedition." This is that expedition.
It ended nowhere near where I thought it would: not with fp4, and not on the 8xlarge I was
aiming for, but on the smallest, cheapest Inferentia2 instance AWS sells — a single inf2.xlarge
with 16 GB of host RAM
— running a 26B-parameter model. Here's the refinement trail, dead ends
included.

The finished port (see the previous article) served the 26B-A4B on a 24xlarge: 12 NeuronCores, 192 GB
HBM, ~$6.49/hr on-demand. It worked, it was correct, and it was overkill for one user asking one
question at a time.
The whole point of a "4B-active" MoE is that it's cheap to run; it shouldn't need
a datacenter-class box to host. The goal: get it onto the bottom-tier inf2.xlarge — 2 cores, 32 GB
HBM, and only 16 GB of host RAM — at ~$0.76/hr. That's 8.6× cheaper.

24xlarge (shipped) inf2.xlarge (goal)
NeuronCores 12 (used 8) 2
HBM 192 GB 32 GB
Host RAM 768 GB 16 GB
On-demand ~$6.49/hr ~$0.76/hr

Two walls stood in the way: the model doesn't fit 32 GB of HBM at bf16, and it doesn't fit 16 GB of host
RAM the normal way. I had to break both.

Wall 1: the memory math, and why "A4B" doesn't save you

The experts are ~93% of the weight. At bf16 the 128 experts are ~45.6 GB — replicate that across TP=2
and you're at ~22.8 GB per core against a 16 GB budget. Top-8 routing reduces compute, not
footprint: all 128 experts must be resident. So the experts alone blow the box.

My first move was the obvious one — int8 the experts. NxD has QuantizedColumnParallel /
QuantizedRowParallel, and (from the prior article) int8-per-channel on this model is numerically
perfect
: token-for-token identical to fp32. Experts drop to ~11.4 GB/rank. Should fit.

It didn't. Could not load the model status=4 Allocation Failure~3–4 GB over the 16 GB core. And
inf2 has no 4-core SKU to split the difference. My conclusion at the time, which I even wrote down: to
close that last 3–4 GB you need fp4 experts.

The fp4 rabbit hole (two of them, both dead ends)

I chased fp4 twice.

First, QuantizedColumnParallel advertises F4E2M1FN_X4. But its state_dict weight is a packed
uint16
microscaling format (32 fp4 → 8 uint16) produced by from_float/preshard_hook — nothing
like int8's five-line quantizer. Then I read the AWS docs plainly: NxD Inference quantization supports
INT8 and FP8 only.
FP8 is 8-bit — same size as int8, so it doesn't help. QuantizedDtype.F4E2M1FN_X4
exists as a constant but isn't a wired-up inference path.

Second, on the newest Neuron 2.31 stack (neuronx-cc 2.26, NxD 0.19) fp4 looked less absent —
there's BLOCKWISE_SYMMETRIC, block_size, from_float. So I tried again, and hit the floor twice:

  • The clean QuantizedColumnParallel fp4 forward calls blockwise_scale_dequantize, which is a CPU-only torch reference (assert device == cpu) — it can't trace to a NeuronCore.
  • The real device path wants the blockwise_mm NKI kernel, which NxD imports from neuronxcc.nki._private.blockwise_mm — but 2.26 ships it under _pre_prod_kernels. Mispathed, pre-prod, import fails.
  • Swapping my DenseExperts for NxD's ExpertMLPs (which has fp4 packing) didn't help either: its blockwise NKI path kernel_asserts, and its use_torch_block_wise=True path crashes torch-xla's shape inference on a data-dependent index op. MoE routing that won't trace — the exact problem the dense trick solved for compute, now back for quantization.

fp4 on inf2 is a wall in this SDK. I'd spent real time being sure it was the only door. It wasn't
even a door.

The breakthrough: I was quantizing the wrong thing

Here's the reframe that unlocked it. I'd been staring at the experts because they're huge. But the
experts were already int8 when I OOM'd. The 3–4 GB I needed wasn't in the experts — it was in the
weights I'd left in bf16. Chiefly one: the tied lm_head, replicated at 1.48 GB per rank.

The fix wasn't smaller experts. It was an all-int8 squeeze of everything still fat:

  1. int8 and shard the lm_head. QuantizedColumnParallel(gather_output=True) slices the 262k-row head across ranks and quantizes it: 1.48 GB → ~0.37 GB/rank. This was the single biggest lever, and it had nothing to do with the experts.
  2. int8 the shared dense MLP (the other half of the dual-path FFN): another ~0.27 GB/rank.
  3. Keep the int8 experts.

Per-rank resident dropped to ~12–13 GB — comfortably under 16 GB. And the output was still right:

Compiler status PASS · MB_TRACED
DEVICE_PARIS True
DEV GEN: 'The capital of France is Paris.'
prefill 232 ms · neff 26.7 GB
Enter fullscreen mode Exit fullscreen mode

The 26B MoE ran on a 2-core inf2.8xlarge. The "not achievable without fp4" conclusion was right
that fp4 was out — and wrong about everything else.

Wall 2: the 8xlarge and the xlarge have the same HBM — but not the same host RAM

Here's the subtlety that trips everyone. inf2.8xlarge and inf2.xlarge have the same 2 NeuronCores
and 32 GB HBM
. The difference is host RAM: 128 GB vs 16 GB. My squeeze fit the device. Would
it fit the host on the cheapest box?

Compiling won't: the ModelBuilder trace holds an fp32 discovery model + a structure model + an fp32
checkpoint dict — ~180 GB peak. That OOMs even the 8xlarge's 128 GB (I added a 100 GB swapfile to get
the compile through, ~40 min). But compiling and deploying are different jobs. Deploying a saved
neff doesn't need the model in host RAM at all — the transformer weights live on the device.

So the xlarge deploy is deliberately slim (deploy_sqz.py / optb_server_sqz.py):

  • Structure (which layers are KV-shared, head dims, sliding window) comes from a meta-device model instantiation — accelerate.init_empty_weights(), ~0 host RAM.
  • Word embeddings come from a standalone 1.48 GB embed_tokens.pt table, loaded once on the host.
  • The neff carries every transformer weight on the device (torch.jit.load + one initialize_with_saved_weights).
  • A 40 GB swapfile absorbs the one-time neff-load peak.

Result on a stock 16 GB inf2.xlarge:

NEFF_LOADED in 112s
DEV GEN: 'The capital of France is Paris.'
PREFILL 250 ms
Enter fullscreen mode Exit fullscreen mode

Host RSS peaked ~11 GB; swap was barely touched. Compile needs 180 GB; deploy needs a laptop's worth.
A 26B model, on a box you'd hesitate to run a 7B on.

The bug that turned Paris into a wall of spaces

Except the first slim run didn't say Paris. It said:

DEV GEN: '                                                              '
DEVICE_PARIS False
Enter fullscreen mode Exit fullscreen mode

The neff was proven (it made Paris at compile). So the deploy was feeding it something wrong. Repeated
identical tokens is the fingerprint of degenerate, near-uniform logits — the classic symptom of
embeddings at the wrong magnitude.

Gemma-4 doesn't use a plain embedding. It uses Gemma4TextScaledWordEmbedding, whose forward is:

return super().forward(input_ids) * self.embed_scale   # embed_scale = hidden_size ** 0.5
Enter fullscreen mode Exit fullscreen mode

The ×√hidden_size (= √2816 ≈ 53) happens inside the embedding, and the model forward does not
re-normalize — it just does hidden_states = inputs_embeds. The neff was traced on scaled embeds. My
slim host path used a plain torch.nn.Embedding and fed unscaled ones — 53× too small. Everything
downstream washed out to noise.

One line:

ie = emb(ids) * (hidden_size ** 0.5)   # match Gemma4TextScaledWordEmbedding
Enter fullscreen mode Exit fullscreen mode

DEV GEN: 'The capital of France is Paris.'. This is the same trap that bit the E2B slim server; when you
move embedding lookup to the host, you inherit whatever the model's embedding class was doing.

Shipping it: 512/128, published, and a clean-pull proof

I recompiled a production 512/128 bucket build (512 total / 128 prompt tokens) — same recipe, ~40 min
on an 8xlarge with swap, neff 26.8 GB, re-validated on the xlarge (loads in 112 s, ~10 GB host peak,
Paris). Then I wrapped it in a slim OpenAI-compatible server and published:

  • Docker Hub xbill9/gemma4-optb-26b:xlarge — a thin image; the entrypoint pulls the ~28 GB of artifacts from the HF repo on first start.
  • HF xbill9/gemma-4-26B-A4B-it-inferentia2-xlarge (public) — neff + embedding table + config + server + Dockerfile.

The final proof was the one that matters to anyone but me: a cold, clean pull. Fresh spot
inf2.xlarge, add swap, docker run, walk away.

READY in 490.9s  slim int8-squeeze, ModelBuilder TP=2, MAX=512 BUCKET=128
{"role":"assistant","content":"The capital of France is Paris."}
{"response":"AWS Inferentia is a purpose-built machine learning accelerator
             designed to provide high-performance, low-cost inference..."}
Enter fullscreen mode Exit fullscreen mode

(No HF_TOKEN needed — the repo is public. The 490 s is one-time cold-EBS neff load, then it serves.)
Terminated the box; net ongoing spend, zero.

The honest caveat

Decode is ~6 tok/s. That's the price of the DenseExperts trick from the last article: computing all
128 experts every token instead of the sparse top-8 — ~16× the necessary expert FLOPs, on 2 cores. It's
correct and it's cheap to host; it is not fast. Making sparse routing actually trace under
ModelBuilder is the real next expedition, and (see the fp4 detour) "the vendor primitive exists" is not
the same as "it traces." For single-user, cost-sensitive, latency-tolerant serving of a 26B on a $0.76/hr
box, the tradeoff is the right one. For a chatbot under load, it isn't yet.

Takeaways

  1. When something's 3 GB over, don't assume it's the obvious 3 GB. I burned days on fp4 experts; the fix was quantizing the replicated lm_head I'd never looked at. Profile the residency, don't eyeball the architecture.
  2. "Not supported" beats "not documented well." fp4 has constants and partial code paths in NxD 0.19 that make it look one commit away. It isn't — the kernels are CPU-only refs or pre-prod. Read the feature guide's supported list and believe it.
  3. Compile-fit and deploy-fit are different budgets. A model that needs 180 GB of host RAM to trace can deploy on 16 GB, because the weights live on the device. Slim host loading + swap is what turns a 24xlarge model into an xlarge product.
  4. Moving embedding lookup to the host means inheriting the embedding class. Gemma's ×√H scale is inside Gemma4TextScaledWordEmbedding; miss it and you get a confident wall of whitespace.
  5. Ship the clean-pull proof. "Works on my validated box" isn't a deliverable; "docker run on a fresh spot instance says Paris" is.

Artifacts

  • Docker Hub: xbill9/gemma4-optb-26b:xlarge
  • HF: xbill9/gemma-4-26B-A4B-it-inferentia2-xlarge (public)
  • Recipe: tp_mb_moe_sqz.py (all-int8 squeeze: int8 experts + sharded int8 lm_head + int8 shared MLP) · deploy_sqz.py / optb_server_sqz.py (slim host-embedding deploy)

A 26B mixture-of-experts, on the cheapest accelerator instance AWS rents, for the price of a large coffee
per day. Written with AI assistance in a Claude Code session; every log line quoted is from a real run on
real hardware.

Top comments (14)

Collapse
 
publiflow profile image
PubliFlow

Good DevOps overview. One critical aspect I'd emphasize is observability — proper structured logging, distributed tracing, and metrics from day one make incident response dramatically faster.

Collapse
 
xbill profile image
xbill Google Developer Experts • Edited

been iterating with small steps. I realized even the model summaries weren't standardized so I have been working on a basic format to make comparisons easier. the bonus is that well structured data can be used in the context

Collapse
 
publiflow profile image
PubliFlow

Standardizing model summaries is a smart move since unstructured outputs make automated comparisons a nightmare. Structuring that data early also feeds directly into an observability pipeline for much better drift detection. What schema are you settling on to normalize those summaries across different runs?

Collapse
 
publiflow profile image
PubliFlow

That iterative approach makes a lot of sense. Standardizing the output format before worrying about agent boundaries is a smart move. We found something similar: once the traces are structured consistently, it becomes much easier to spot which steps actually benefit from being split out vs which ones are fine staying in the same pipeline. Curious what format you settled on for the summaries?

Thread Thread
 
xbill profile image
xbill Google Developer Experts

I don't have it in the repo yet but did a rough outline at a high level :

xbill@penguin:~/tpu-skill-agy/benchmarks/reports$ more 2026-07-21-gemma4-e2b-v6e1.json
{
"schema_version": "1.0",
"run": {
"id": "2026-07-21-gemma4-e2b-v6e1",
"date": "2026-07-21",
"source": "devto-post.md",
"notes": "Single benchmark run per configuration; a kernel study on this stack measured run-to-run cv <= 0.3% under
greedy decoding with static shapes."
},
"hardware": {
"accelerator": "tpu-v6e",
"chips": 1,
"hbm_gb_per_chip": 32,
"machine_type": "ct6e-standard-1t",
"host": {
"cloud": "gcp",
"zone": "europe-west4-a",
"provisioning": "flex-start",
"instance_name": "vllm-gemma4-e2b",
"max_run_duration_hours": 4
},
"pricing": {
"currency": "USD",
"rate_per_chip_hour": 1.35,
"source": "cloud.google.com/products/dws/pricing"
}
},
"model": {
"id": "google/gemma-4-E2B-it",
"family": "gemma-4",
"parameters_b": 2,
"weights_dtype": "bfloat16",
"quantization": "none",
"kv_cache_dtype": "fp8_e5m2",
"max_model_len": 65536,
"architecture_notes": "KV sharing: only 15 of 35 layers hold KV tensors (num_kv_shared_layers=20), single 256-dim KV
head; ~15 KiB KV per token in bf16, ~7.5 KiB under fp8."
},
"software": {
"engine": "vllm",
"version": "0.23.1rc1.dev1076+g5c342876a",
"container_image": "vllm/vllm-tpu:nightly",
"backend": "tpu-inference (JAX)",
"tensor_parallel_size": 1,
"serve_args": [
"--tensor-parallel-size 1",
"--max-model-len 65536",
"--gpu-memory-utilization 0.9",
"--max_num_batched_tokens 4096",
"--disable_chunked_mm_input",
"--enable-auto-tool-choice",
"--tool-call-parser gemma4",
"--reasoning-parser gemma4",
"--limit-mm-per-prompt {\"image\":4,\"audio\":1}"
]
},
"load_matrix": [
{
"model_id": "google/gemma-4-E2B-it",
"backend": "tpu-inference (JAX)",
"verdict": "loads"
},
{
"model_id": "google/gemma-4-E2B-it-qat-w4a16-ct",
"backend": "tpu-inference (JAX)",
"verdict": "fails",
"error": "int4 compressed-tensors scheme unimplemented for E2B's per_layer_model_projection",
"issue": "github.com/vllm-project/tpu-infere..."
},
{
"model_id": "google/gemma-4-E2B-it-qat-q4_0-unquantized",
"backend": "tpu-inference (JAX)",
"verdict": "fails",
"error": "loader demands self_attn.k_norm.weight for KV-shared layers 15-34 that the checkpoint legitimately omits
",
"issue": "github.com/vllm-project/tpu-infere..."
},
{
"model_id": "google/gemma-4-E2B-it-qat-q4_0-unquantized",
"backend": "torchax (MODEL_IMPL_TYPE=vllm)",
"verdict": "fails",
"error": "identical missing-weights error as the JAX path",
"issue": "github.com/vllm-project/tpu-infere..."
}
],
"throughput": {
"workload": {
"tool": "vllm bench serve",
"dataset": "random",
"input_len": 1024,
"output_len": 128,
"num_prompts": 100,
"runs_per_point": 1,
"noise_floor_pct": 10
},
"sweep": [
{
"concurrency": 1,
"request_rate_rps": 1.64,
"output_tok_per_s": 209,
"total_tok_per_s": 1884,
"per_stream_tok_per_s": 213,
"ttft_ms": { "median": 16, "p99": 17 },
"tpot_ms": { "median": 4.7 }
},
{
"concurrency": 8,
"request_rate_rps": 9.44,
"output_tok_per_s": 1209,
"total_tok_per_s": 10878,
"per_stream_tok_per_s": 161,
"ttft_ms": { "median": 27, "p99": 99 },
"tpot_ms": { "median": 6.2 }
},
{
"concurrency": 32,
"request_rate_rps": 12.78,
"output_tok_per_s": 1636,
"total_tok_per_s": 14721,
"per_stream_tok_per_s": 57,
"ttft_ms": { "median": 155, "p99": 189 },
"tpot_ms": { "median": 17.5 }
},
{
"concurrency": 64,
"request_rate_rps": 16.72,
"output_tok_per_s": 2140,
"total_tok_per_s": 19262,
"per_stream_tok_per_s": 39,
"ttft_ms": { "median": 122, "p99": 349 },
"tpot_ms": { "median": 25.3 }
},
{
"concurrency": 100,
"request_rate_rps": 17.31,
"output_tok_per_s": 2215,
"total_tok_per_s": 19938,
"per_stream_tok_per_s": 27,
"ttft_ms": { "median": 833, "p99": 1573 },
"tpot_ms": { "median": 36.8 }
}
]
},
"capabilities": [
{
"domain": "tool_calling",
"verdict": "pass",
"conditions": { "tool_call_parser": "gemma4", "enable_auto_tool_choice": true, "temperature": 0 },
"probes": [
{ "name": "simple-call", "verdict": "pass", "latency_ms": 166, "observed": "correct tool, inferred optional unit
arg from phrasing" },
{ "name": "result-synthesis", "verdict": "pass", "latency_ms": 140, "observed": "tool result fed back yields cle
an natural-language answer" },
{ "name": "no-tool-restraint", "verdict": "pass", "latency_ms": 97, "observed": "answered directly, no spurious
call" },
{ "name": "parallel-calls", "verdict": "pass", "latency_ms": 150, "observed": "both calls emitted in one turn, c
orrect args each" },
{ "name": "underspecified", "verdict": "pass", "latency_ms": 44, "observed": "asked for the missing city instead
of hallucinating a call" }
]
},
{
"domain": "structured_output",
"verdict": "partial",
"conditions": { "enable_thinking": true },
"probes": [
{ "name": "json_schema-thinking-off", "verdict": "fail", "observed": "free prose with 200 status; strict/guided_
json/structured_outputs spellings all unenforced" },
{ "name": "json_object-thinking-off", "verdict": "partial", "observed": "fenced code block, array instead of obj
ect, invented enum value" },
{ "name": "json_schema-thinking-on", "verdict": "pass", "observed": "exact schema conformance: bare JSON object,
typed integer, ASAP mapped to high enum" }
],
"notes": "With --reasoning-parser gemma4, grammar enforcement engages only after the reasoning section ends; think
ing off means it never engages and unconstrained prose ships with a 200. Keep client-side validation regardless."
},
{
"domain": "reasoning",
"verdict": "pass",
"conditions": { "enable_thinking": true },
"probes": [
{ "name": "default", "verdict": "not_tested", "observed": "no reasoning traces on any prompt; off by default" },
{ "name": "enable-thinking", "verdict": "pass", "observed": "parser cleanly splits thinking trace from terse ans
wer; ~2.4x completion tokens" }
]
},
{
"domain": "vision",
"verdict": "pass",
"conditions": { "limit_mm_per_prompt": { "image": 4, "audio": 1 }, "image_input": "base64 data URI", "temperature"
: 0 },
"probes": [
{ "name": "describe", "verdict": "pass", "latency_ms": 197, "observed": "two tabby cats, pink surface, remote co
ntrol identified" },
{ "name": "count-attributes", "verdict": "pass", "latency_ms": 421, "observed": "2 animals, both cats, remote an
d blanket identified" },
{ "name": "scene", "verdict": "pass", "latency_ms": 329, "observed": "bear lying down in grassy outdoor environm
ent" },
{ "name": "room-inventory", "verdict": "pass", "latency_ms": 874, "observed": "wall-mounted TV, shelving, furnit
ure correctly enumerated" }
],
"notes": "~280 prompt tokens per image. Server-side fetching of external image URLs is flaky (intermittent 422s) —
base64 data URIs are the reliable path. First multimodal request after boot can 422 while the processor warms; retry on
ce."
}
],
"memory": {
"usable_hbm_gib": 31.24,
"weights_gib": 5.75,
"kv_cache_gib": 16.3,
"workspace_gib": 6,
"kv_bytes_per_token": 7680,
"resident_kv_tokens": 1100000,
"notes": "Measured on a bf16-KV boot at 0.9 utilization (28.12 GiB working set); kv_bytes_per_token/resident_kv_toke
ns are for the default fp8_e5m2 cache. fp8 vs bf16 KV: 6 of 6 greedy outputs byte-identical."
},
"startup": {
"time_to_healthy_s": 510,
"engine_init_s": 404,
"compile_s": 329,
"notes": "From VM RUNNING: Docker ~60s, image pull ~360s, weights+compile+health ~510s. 200 GB boot disk required; 1
0 GB default cannot hold the vLLM image."
},
"cost": {
"per_m_output_tokens": [
{ "operating_point": "saturation", "output_tok_per_s": 2215, "usd": 0.17 },
{ "operating_point": "c=64", "output_tok_per_s": 2140, "usd": 0.18 },
{ "operating_point": "c=8", "output_tok_per_s": 1209, "usd": 0.31 },
{ "operating_point": "single-stream", "output_tok_per_s": 209, "usd": 1.79 }
],
"cold_start_usd": 0.24,
"comparisons": [
{
"name": "gemini-2.5-flash-lite",
"usd_per_m_output_tokens": 0.40,
"source": "ai.google.dev/gemini-api/docs/pricing"
}
],
"notes": "Breakeven vs Flash-Lite at ~940 sustained output tok/s (~c=8 held continuously). A full 4-hour session cos
ts $5.40 and delivers ~30M output tokens at saturation."
},
"issues": [
{
"url": "github.com/vllm-project/tpu-infere...",
"summary": "Gemma 4 E2B loader demands per-layer k_norm/v_norm that KV-shared layers legitimately lack; blocks bot
h QAT checkpoint variants",
"status": "open"
}
],
"notes": [
"Direct SSH silently times out on some networks even when the VPC allows tcp:22 — use IAP tunneling (gcloud compute
ssh --tunnel-through-iap, or start-iap-tunnel for port 8000).",
"vLLM auto-selects fp8_e5m2 KV cache on v6e — the largest memory consumer is 8-bit before any weight quantization.",
"Capacity planning: run at <=64 concurrent streams; ceiling ~17 req/s at this workload shape; knee between c=32 and
c=64."
]
}

Thread Thread
 
publiflow profile image
PubliFlow

That JSON schema structure is excellent - keeping run metadata and hardware configuration explicitly versioned makes benchmarks genuinely reproducible. The KV sharing optimization on the E2B is a smart move; 7.5 KiB per token under fp8 is a real throughput win at scale. Have you looked into whether the shared layers show asymmetric latency under higher concurrency, or is it uniform across the KV-shared block?

Thread Thread
 
publiflow profile image
PubliFlow

That JSON structure looks incredibly clean, especially including the schema_version for future-proofing and capturing the kernel study context directly in the notes. Since you are currently doing a single benchmark run per configuration, you might eventually want to add a stats object to track variance or p-values once you scale up to multiple runs. It gives you a solid baseline to build out the CI pipeline around.

Collapse
 
jam-techcirkle profile image
James Sanderson

The "A4B saves compute, not footprint" point is the one people keep missing - top-8 routing gets sold as an efficiency win, but if all 128 experts have to stay resident then your real constraint is HBM, not FLOPs, and no amount of clever routing buys that back. Curious what int8 did to output quality here versus the bf16 baseline on the 24xlarge - did you see measurable drift on the experts, or was it clean enough to not bother with per-tensor calibration? The 8.6× cost delta is a hard number to argue with if quality held.

Collapse
 
voltagegpu profile image
VoltageGPU

Interesting setup with the inf2.24xlarge — I'm curious how the sparse execution in the MoE layers interacted with the AWS Graviton-based instance's memory hierarchy. Have you noticed any bottlenecks when scaling up the number of active experts per token? On VoltageGPU, we often see similar patterns where model parallelism needs careful alignment with hardware NUMA domains.

Collapse
 
publiflow profile image
PubliFlow

This is a solid CI/CD foundation. In practice, I've found that the real complexity comes from managing environment parity and secrets. Have you explored HashiCorp Vault or external secrets operators for K8s?

Collapse
 
xbill profile image
xbill Google Developer Experts

The goal with the first version was to keep the deployment bare bones with as few external dependencies as possible. The Google cloud project is needed for the IAM calls and TPUs so the secrets manager came with the dinner.

GKE and more advanced Deployments are on my list.

Collapse
 
unitbuilds profile image
UnitBuilds

Solid setup, though imo, quantizing the head is just about as degrading as quantizing the tokenizer. You lose alot of knowledge that way...

Just a note on MoE, the purpose isnt to make it run small, so you can run it on cheap hardware, its purpose it to make it run cheap, so you can scale higher. A single enterprise gpu can handle it no problem, but the real gain is parallelism, where you run multiple agents off a single set of weights. That's the true benefit of MoE structure. For the same price as running 1 user and it's overkill, you can run 20+ users and it would still be overkill, instead of hitting a brick wall. If you look at the current industry in cloud driven models. All 'flash' models are MoE, so they have sufficient intelligence, while running super fast and for the new age of models, where we're seeing 2.4t, 2.8t params, even if you can fit it on your server rack, it's too computationally heavy as a dense model, you have to make it MoE for it to be viable at scale.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.