Strata's DeepSeek not offered on cards its engine was not built for, and refused there by the agent
CI / test (push) Successful in 9m42s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ilker ManapandClaude Opus 5.5 committed 2026-10-30 13:00:21 +01:00
1 parent 104b60fbf8
commit f41c96d30f
13 files changed
+90 -6

No files matched your search

+2
View File
@@ -1896,6 +1896,8 @@ served only from a definition written by hand. In order:
**C. Operating it.**
- N9. `ctl engine-check strata`: the flags of setup.py and server.py, which drift between versions.
- N10. `ctl engine-build NODE strata cuda12|cuda13`, as vLLM has.
- N11a. Strata's per-replica state directories (engine-home/strata/<replica>) are left behind when a replica stops;
remove them with it.
- N11. Disk for the prepared pack and draft layer (and DeepSeek V4.1's 240–280 GB), cleaned with the weights; a
first start's preparation within the startup timeout.
- N12. docs/install.md: Strata in the engines table, a section with a profile, its memory and first-run time;
+3
View File
@@ -40,6 +40,9 @@ APIs change between minors without a deprecation period.
- **A repository that keeps each quantisation in a directory of its own** (ISTA-DASLab's `IQ2_XS/`, `IQ3_S/`) listed
no weights: its file tree is now read recursively, by the explorer, the plan and `ctl model serve`.
- **DeepSeek V4.1 offered on a card its engine was not built for.** Strata's DeepSeek engine runs on RTX 30 (compute
8.6) and newer; on a Turing card the tab and the plan offered it, and Strata's setup refused it once placed. Now
neither offers it there, the tab says why, and the agent refuses such a profile before starting it.
## v0.16.0 — 2026-10-30
+9
View File
@@ -9,6 +9,8 @@ import (
"regexp"
"strconv"
"sync/atomic"
"gitea.mynodes.xyz/ilker/llmgw/internal/strata"
)
// StrataConfig locates a Strata installation.
@@ -133,6 +135,13 @@ func (*Strata) Validate(p Profile, gpus []GPUInfo) error {
if err := requireComputeCapability(p, gpus, 6.0, "strata"); err != nil {
return err
}
// A family whose engine needs more: said now, rather than by Strata's
// setup after the replica was placed here.
if fam, ok := strata.FamilyNamed(strata.ArgValue(p.Args, "--family")); ok && fam.MinCC > 0 {
if err := requireComputeCapability(p, gpus, fam.MinCC, "strata's "+fam.Title+" engine"); err != nil {
return err
}
}
return validateCommon(p, gpus)
}
+13
View File
@@ -98,3 +98,16 @@ func TestAStrataNamedByHandIsReportedWithItsVersion(t *testing.T) {
t.Error("reported without its engine")
}
}
func TestStrataRefusesDeepSeekOnACardItsEngineWasNotBuiltFor(t *testing.T) {
s := &Strata{}
p := Profile{Name: "p", Engine: "strata", ModelPath: "/m", TP: 1, GPUsPerNode: 1, Args: []string{"--family", "deepseek41", "--size", "IST-DAS-1.75bpw"}}
gpus := []GPUInfo{{Index: 0, Name: "Quadro RTX 6000", ComputeCapability: "7.5"}}
if err := s.Validate(p, gpus); err == nil || !strings.Contains(err.Error(), "8.6") {
t.Errorf("DeepSeek on 7.5: %v", err)
}
p.Args = []string{"--family", "qwen", "--size", "IQ2_XS"}
if err := s.Validate(p, gpus); err != nil {
t.Errorf("Qwen on 7.5: %v", err)
}
}
+5
View File
@@ -1954,6 +1954,11 @@ func PoolNodesOf(nodes []NodeView) []modelplan.PoolNode {
if len(n.Fabrics) > 0 {
p.Fabric = n.Fabrics[0]
}
for _, c := range n.ComputeCapabilities {
if v, err := strconv.ParseFloat(c, 64); err == nil && v > p.CC {
p.CC = v
}
}
if l := n.Load; l != nil && l.MemTotal > 0 {
p.HostFreeGB = int((l.MemTotal - l.MemUsed) >> 30)
}
+2
View File
@@ -55,6 +55,8 @@ type PoolNode struct {
Kinds []PoolKind
// Engines are the engines the node has installed.
Engines []string
// CC is its newest card's compute capability, 0 when not known.
CC float64
}
// PoolKind is one class of a node's devices.
+6
View File
@@ -24,12 +24,18 @@ func StrataOptions(family string, arts []Artifact, nodes []PoolNode) []Option {
continue
}
need := float64(size.MemoryGB())
fam, _ := strata.FamilyNamed(family)
byClass := map[string]*Option{}
var order []string
for _, n := range nodes {
if !slices.Contains(n.Engines, "strata") || n.HostMemGB <= 0 {
continue
}
// A family whose engine needs a newer card: refused by Strata on
// this one, after the node was chosen.
if fam.MinCC > 0 && n.CC > 0 && n.CC < fam.MinCC {
continue
}
have := float64(n.HostMemGB) * hostShare
if need > have {
continue
+19
View File
@@ -30,3 +30,22 @@ func TestStrataIsOfferedOnANodeWithItTheCardAndTheRAM(t *testing.T) {
t.Errorf("%q %q", o.Label(), o.MemoryText())
}
}
// DeepSeek's engine is built for RTX 30 and newer: not offered on a Turing
// card, which Strata's setup refuses after the replica is placed.
func TestDeepSeekOnStrataNeedsANewerCard(t *testing.T) {
arts := []Artifact{{Name: "IST-DAS-1.75bpw.gguf", Format: "gguf"}}
node := func(cc float64) []PoolNode {
return []PoolNode{{ID: "n", Class: "6000-24g", GPUMemGB: 24, GPUs: 1, FreeGPUs: 1, HostMemGB: 251,
Engines: []string{"strata"}, CC: cc}}
}
if got := StrataOptions("deepseek41", arts, node(7.5)); len(got) != 0 {
t.Errorf("offered on 7.5: %+v", got)
}
if got := StrataOptions("deepseek41", arts, node(8.9)); len(got) != 1 {
t.Errorf("not offered on 8.9: %+v", got)
}
if got := StrataOptions("qwen", []Artifact{{Name: "IQ2_XS.gguf"}}, node(7.5)); len(got) != 1 {
t.Errorf("Qwen not offered on 7.5: %+v", got)
}
}
+5 -1
View File
@@ -26,6 +26,10 @@ type Family struct {
// Engine is a family that runs on an engine path of its own, with a
// download of its own (DeepSeek V4.1).
Engine bool
// MinCC is the compute capability its engine needs of an NVIDIA card,
// above Strata's own 6.0; 0 for none. DeepSeek's engine is built for
// RTX 30 (8.6) and newer only.
MinCC float64
}
// Size is one of a family's sizes: setup's --model, which llmgw's profile
@@ -56,7 +60,7 @@ var Families = []Family{
{Name: "gyro", Model: "qwen3.8-flash-next-gyro", Title: "Qwen3.8-Flash-Next (Gyro)", Repo: "agentionai/Qwen3.8-Flash-Next-Gyro-GGUF"},
{Name: "nvfp4", Model: "qwen3.8-flash-next-nvfp4", Title: "Qwen3.8-Flash-Next (NVFP4)"},
{Name: "qwen36", Model: "qwen3.6-35b-a3b", Title: "Qwen3.6-35B-A3B", Repo: "unsloth/Qwen3.6-35B-A3B-MTP-GGUF"},
{Name: "deepseek41", Model: "deepseek-v4.1-flash", Title: "DeepSeek V4.1-Flash", Repo: "ISTA-DASLab/DeepSeek-V4.1-Flash-1017-GSQ-RCO-GGUF", Engine: true},
{Name: "deepseek41", Model: "deepseek-v4.1-flash", Title: "DeepSeek V4.1-Flash", Repo: "ISTA-DASLab/DeepSeek-V4.1-Flash-1017-GSQ-RCO-GGUF", Engine: true, MinCC: 8.6},
}
// Sizes are the sizes Strata 0.2.7 runs, and which families have each.
+18
View File
@@ -65,6 +65,8 @@ func (p *AccountPages) strataView(l *Lang) *strataView {
sr.Fits, sr.Runs = true, l.T("explore.strata", opts[0].Class, l.Num(opts[0].NeedGB, 0))
case len(v.Nodes) == 0:
sr.Runs = l.T("strata.no_node")
case f.MinCC > 0 && cardsOlderThan(pool, f.MinCC):
sr.Runs = l.T("strata.old_card", l.Num(f.MinCC, 1))
default:
sr.Runs = l.T("strata.no_room", s.MemoryGB())
}
@@ -75,6 +77,22 @@ func (p *AccountPages) strataView(l *Lang) *strataView {
return v
}
// cardsOlderThan says whether every node with Strata has a card of a
// compute capability below cc, as far as they say.
func cardsOlderThan(pool []modelplan.PoolNode, cc float64) bool {
older := false
for _, n := range pool {
if !slices.Contains(n.Engines, "strata") {
continue
}
if n.CC == 0 || n.CC >= cc {
return false
}
older = true
}
return older
}
// serveStrata adds a model of a family Strata fetches itself: its source
// the repository, its replica on a card of the class the plan found.
func (p *AccountPages) serveStrata(ctx context.Context, l *Lang, by, family, size string) (string, error) {
+4 -3
View File
@@ -15,7 +15,7 @@ type strataFleet struct{ fakeFleet }
func (strataFleet) Nodes() []adminapi.NodeView {
return []adminapi.NodeView{{ID: "cuda01", State: "ready", GPUTotal: 1, GPUFree: 1, MemoryGB: 251,
Classes: []string{"6000-24g"}, Engines: []string{"llamacpp", "strata"}}}
Classes: []string{"6000-24g"}, Engines: []string{"llamacpp", "strata"}, ComputeCapabilities: []string{"7.5"}}}
}
func TestTheStrataTabListsWhatRunsHereAndFetchesASize(t *testing.T) {
@@ -31,13 +31,14 @@ func TestTheStrataTabListsWhatRunsHereAndFetchesASize(t *testing.T) {
body := mirrorGet(t, mux, "/admin/mirror?tab=strata").Body.String()
for _, want := range []string{"Strata is installed on: cuda01", "Qwen3.8-Flash-Next", "IQ2_XS",
"1× 6000-24g with Strata, 52 GB of RAM", `name="size" value="IQ2_XS"`, "Strata fetches these onto the node itself"} {
"1× 6000-24g with Strata, 52 GB of RAM", `name="size" value="IQ2_XS"`, "Strata fetches these onto the node itself",
"compute capability 8.6 or newer"} {
if !strings.Contains(body, want) {
t.Errorf("the tab lacks %q", want)
}
}
// Unsloth's Q8_0 keeps 140 GB: it runs here; nothing past the node's RAM does.
if strings.Contains(body, `value="UD-Q8_K_XL"`) {
if strings.Contains(body, `value="UD-Q8_K_XL"`) || strings.Contains(body, `value="IST-DAS-1.75bpw"`) {
t.Error("offered DeepSeek's 306 GB size, which no node holds, and which Strata fetches itself")
}
+2 -1
View File
@@ -278,5 +278,6 @@
"strata.err.not_servable": "%s is fetched into the mirror first, then served from its version",
"strata.msg.served": "%s added: its first start fetches about %s GB onto the node and prepares it, which can take hours on a slow link; Replicas shows how far it is.",
"strata.pack_files": "part of Strata's ready-made %s %s pack: served whole from the mirror's Strata tab, Strata fetching it onto the node",
"strata.unknown_pack": "a pack made for Strata that Strata 0.2.7 does not know: its setup refuses it, and llama.cpp cannot read it"
"strata.unknown_pack": "a pack made for Strata that Strata 0.2.7 does not know: its setup refuses it, and llama.cpp cannot read it",
"strata.old_card": "its engine needs an NVIDIA card of compute capability %s or newer (RTX 30 on); the nodes with Strata have older ones"
}
+2 -1
View File
@@ -271,5 +271,6 @@
"strata.err.not_servable": "%s önce aynaya indirilir, sonra sürümünden sunulur",
"strata.msg.served": "%s eklendi: ilk açılışında node'a yaklaşık %s GB indirip hazırlar; yavaş bağlantıda saatler sürebilir. İlerleyişi Replikalar gösterir.",
"strata.pack_files": "Strata'nın hazır %s %s paketinin parçası: aynanın Strata sekmesinden bütün olarak sunulur, Strata onu node'a kendisi indirir",
"strata.unknown_pack": "Strata için hazırlanmış ama Strata 0.2.7'nin tanımadığı bir paket: kurulumu onu reddeder, llama.cpp de okuyamaz"
"strata.unknown_pack": "Strata için hazırlanmış ama Strata 0.2.7'nin tanımadığı bir paket: kurulumu onu reddeder, llama.cpp de okuyamaz",
"strata.old_card": "motoru compute capability %s ya da daha yeni bir NVIDIA kartı ister (RTX 30 ve sonrası); Strata kurulu node'ların kartları daha eski"
}