mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-17 04:10:04 +02:00
Strata : paquet AJEAN MoE 1.1, reprise automatique d'une installation 1.0
Repris d'AJEAN 9c7423bf (v0.19.0, renumérotée v0.18.1 par e7b024ad) :
- release moe-v1.1 d'AJEAN, empreintes SHA-256 reprises telles qu'AJEAN les
publie dans son backend_moe.go ;
- avec une carte d'aide, la lecture d'un prompt passe par elle
(STRATA_PREFILL_HELPER_SOURCE=1) et le chemin direct ne garde que les
ajouts sous 48 jetons (--short-read 48 au lieu de 150) ;
- mode hors RAM : réserve de VRAM de la carte d'aide à 640 Mio, contexte
plafonné à 131 072 jetons, marge de RAM portée de 7 à 8 Go (le moteur 1.1
prend ~1 Go de plus) ;
- strataMigrate (moeMigrate d'AJEAN) : au premier lancement d'un modèle
installé avec la 1.0, `loki serve` pose les sources 1.1, reprend
l'environnement Python par un lien quand les dépendances n'ont pas changé,
installe le moteur 1.1, recopie la config de l'installeur en réécrivant ses
chemins, puis repointe les presets et la config vivante ensemble
(l'empreinte du preset actif suit). En cas d'échec, rien n'est réécrit et
la 1.0 continue de tourner.
Les correctifs propres à Loki restent : placement des experts selon la RAM
disponible et mode « depuis le disque » (6aaf9360).
Façade Rust : mêmes constantes et même configuration de lancement
(strata/mod.rs) ; la migration reste au Go, seul à servir un preset Strata.
Journal de parité régénéré sous Linux : noms du paquet tirés des constantes,
étapes du seuil du mode hors RAM recalées sur la nouvelle marge, étape du
contexte plafonné ajoutée.
La consolidation de Jean la nuit et le niveau de réflexion du moteur MoE
(même commit amont) ne sont pas repris : Loki n'a ni Jean ni ce raccourci.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
00e09a71e3
commit
9792953d62
12 files changed
+950
-384
No files matched your search
@@ -56,11 +56,13 @@ expose à la place un export/import de paquet chiffré en fichier local.
|
||||
|
||||
Le second moteur de Loki (`internal/loki/backend_strata.go`) est
|
||||
**[Strata](https://github.com/Niko1221/Strata)** (MIT), spécialisé dans
|
||||
Qwen3.8-Flash-Next. Son intégration est reprise d'AJEAN (« AJEAN MoE 1.0 »,
|
||||
Qwen3.8-Flash-Next. Son intégration est reprise d'AJEAN (« AJEAN MoE 1.1 »,
|
||||
`backend_moe.go`) : Loki télécharge le paquet figé publié par AJEAN sur sa
|
||||
release `moe-v1.0` (sources de Strata et binaire Linux CUDA 12 compilé, avec
|
||||
les modifications d'AJEAN), vérifié par SHA-256. Ni Strata ni le modèle ne sont
|
||||
inclus dans l'image : ils sont téléchargés à la demande.
|
||||
release `moe-v1.1` (sources de Strata et binaire Linux CUDA 12 compilé, avec
|
||||
les modifications d'AJEAN), vérifié par SHA-256 avec les empreintes publiées
|
||||
par AJEAN. La reprise automatique d'une installation 1.0 (`strataMigrate`) est
|
||||
reprise d'AJEAN (`moeMigrate`). Ni Strata ni le modèle ne sont inclus dans
|
||||
l'image : ils sont téléchargés à la demande.
|
||||
|
||||
## Services externes
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ Loki a deux moteurs, et le choix se fait **par preset** (clé `ENGINE`) :
|
||||
- **[Strata](https://github.com/Niko1221/Strata)** — spécialisé dans
|
||||
**Qwen3.8 Flash Next** (MoE de 125 B) : les experts sont répartis entre
|
||||
VRAM, RAM et disque pour faire tourner ce modèle sur une carte de joueur.
|
||||
Intégration reprise d'AJEAN (paquet figé « AJEAN MoE 1.0 », vérifié par
|
||||
Intégration reprise d'AJEAN (paquet figé « AJEAN MoE 1.1 », vérifié par
|
||||
SHA-256).
|
||||
|
||||
**Paramètres → Moteur → Strata** : la fenêtre lit la machine (cartes, RAM,
|
||||
@@ -122,6 +122,17 @@ basculer dessus lance Strata, basculer sur un autre preset revient à llama.cpp.
|
||||
Son engrenage ouvre les réglages propres à Strata (contexte jusqu'à 262 144,
|
||||
cache KV fp16/8 bits, prédiction MTP, lecture des images, carte d'appoint).
|
||||
|
||||
Depuis le paquet 1.1, la carte d'appoint calcule elle-même ses experts à la
|
||||
lecture des prompts (au lieu de les recopier vers la principale) : les ajouts
|
||||
de 100 à 200 jetons se lisent ~30 à 40 % plus vite (mesures d'AJEAN). Un modèle
|
||||
installé avec la 1.0 passe à la 1.1 **à son premier lancement**, sans
|
||||
réinstallation : Loki télécharge le nouveau paquet (~340 Mo), reprend
|
||||
l'environnement Python et la configuration de la 1.0 (le dossier
|
||||
`/data/strata/ajean-moe-1.0` doit donc rester en place) et réécrit le preset.
|
||||
En cas d'échec, la 1.0 continue de tourner et la raison est dans le journal du
|
||||
moteur. En mode « hors RAM », le contexte est plafonné à 131 072 jetons (au-delà,
|
||||
le cache KV verrouillé en RAM ne tient plus).
|
||||
|
||||
Pré-requis : Linux + NVIDIA RTX 20 ou plus récente (8 Go de VRAM minimum, une
|
||||
deuxième carte est utilisée comme carte d'appoint), environ 46 Go de RAM pour
|
||||
la plus petite qualité, pilote compatible CUDA 12.8. Le conteneur doit pouvoir
|
||||
|
||||
+126
-15
@@ -5,11 +5,13 @@ package loki
|
||||
// répartit les experts entre VRAM, RAM et disque pour faire tenir le modèle sur
|
||||
// une carte de joueur.
|
||||
//
|
||||
// Repris d'AJEAN (backend_moe.go, « AJEAN MoE 1.0 ») : le moteur est le paquet
|
||||
// FIGÉ publié par AJEAN sur sa release GitHub moe-v1.0 — sources de Strata et
|
||||
// Repris d'AJEAN (backend_moe.go, « AJEAN MoE 1.1 ») : le moteur est le paquet
|
||||
// FIGÉ publié par AJEAN sur sa release GitHub moe-v1.1 — sources de Strata et
|
||||
// binaire Linux CUDA 12 compilé et validé par l'auteur d'AJEAN (avec ses
|
||||
// modifications : experts de la carte d'appoint gardés hors RAM). Les deux
|
||||
// fichiers sont vérifiés par SHA-256 avant usage.
|
||||
// modifications : experts de la carte d'appoint gardés hors RAM et, depuis la
|
||||
// 1.1, calculés par elle à la lecture des prompts). Les deux fichiers sont
|
||||
// vérifiés par SHA-256 avant usage. Un modèle installé avec la 1.0 passe à la
|
||||
// 1.1 à son premier lancement (strataMigrate).
|
||||
//
|
||||
// Le choix du moteur se fait par PRESET : ENGINE=strata. Sans la clé (ou
|
||||
// ENGINE=llamacpp), rien ne change, llama-server reste le moteur.
|
||||
@@ -47,11 +49,12 @@ import (
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
// Paquet figé (release moe-v1.0 d'AJEAN). Le moteur est compilé en CUDA 12.8,
|
||||
// Paquet figé (release moe-v1.1 d'AJEAN). Le moteur est compilé en CUDA 12.8,
|
||||
// mode portable AVX2, sm_75/80/86/89/120 : RTX 20 à 50. Un moteur installé d'un
|
||||
// autre paquet est remplacé au lancement (strataEnsureEngine).
|
||||
// autre paquet est remplacé au lancement (strataEnsureEngine), une installation
|
||||
// d'une version précédente est reprise (strataMigrate).
|
||||
const (
|
||||
strataVersion = "1.0"
|
||||
strataVersion = "1.1"
|
||||
strataSrcAsset = "ajean-moe-src-" + strataVersion + ".tar.gz"
|
||||
strataEngineAsset = "ajean-moe-engine-" + strataVersion + "-linux-x64-cuda12.zip"
|
||||
// strataEngineLocal : le nom sous lequel l'installeur attend le moteur (CUDA12_ASSET).
|
||||
@@ -69,10 +72,11 @@ var (
|
||||
strataDiskFree = diskFree
|
||||
)
|
||||
|
||||
// strataAssetSHA : empreintes des fichiers de la release, vérifiées avant usage.
|
||||
// strataAssetSHA : empreintes des fichiers de la release, vérifiées avant usage
|
||||
// (celles qu'AJEAN publie dans son backend_moe.go pour moe-v1.1).
|
||||
var strataAssetSHA = map[string]string{
|
||||
strataSrcAsset: "5747f69426973d957e4f9894a8e3333c6ef0d6ac8565e26ddb8d36f52211cb3b",
|
||||
strataEngineAsset: "b5851bc138ab32ca3ffefc16bf91c8f557e4d503503473a22f2b6c9e9b8fd34c",
|
||||
strataSrcAsset: "5a72a90f2182ff0ccab2bdbd7cff15598a21ad94501aa19de2b1b18e2dbc8115",
|
||||
strataEngineAsset: "8c717206ee90120f967445169dc39bb11beffdad3d592c75ae08f75bec72f0d3",
|
||||
}
|
||||
|
||||
// Valeurs de la clé ENGINE d'un preset.
|
||||
@@ -132,8 +136,14 @@ const strataLowRAMHeadroomGB = 10
|
||||
|
||||
// strataDropHeadroomGB : RAM à laisser à côté des experts verrouillés quand la
|
||||
// carte d'aide garde les siens hors RAM (mesuré par AJEAN : 46 Go de RAM,
|
||||
// 34,7 Gio d'experts verrouillés, ~2,3 Go encore libres).
|
||||
const strataDropHeadroomGB = 7
|
||||
// 34,7 Gio d'experts verrouillés, ~2,3 Go encore libres ; le moteur 1.1 prend
|
||||
// ~1 Go de plus que la 1.0).
|
||||
const strataDropHeadroomGB = 8
|
||||
|
||||
// strataDropMaxCtx : contexte maximal en mode hors RAM. Le cache KV au-delà de
|
||||
// la part en VRAM est verrouillé en RAM : à 167 936 jetons, le serveur de test
|
||||
// d'AJEAN tombait à 1,3 Go libres dès la première requête (moteur 1.1).
|
||||
const strataDropMaxCtx = 131072
|
||||
|
||||
// strataHelperExpertsGB : ce que la carte d'aide garde d'experts (sa VRAM moins
|
||||
// le contexte CUDA, l'encodeur d'images et la marge : 5,3 Gio sur une 3070 8 Go).
|
||||
@@ -870,7 +880,8 @@ func strataFindConfig(quant string) (string, error) {
|
||||
//
|
||||
// - --prefill 16384 : +15 % de lecture sur les longs prompts (40K) ;
|
||||
// - --short-read 150 : les petits ajouts (< 150 jetons) sont lus comme en
|
||||
// génération, sans le coût fixe du chemin par blocs : ~40 % plus rapides ;
|
||||
// génération, sans le coût fixe du chemin par blocs : ~40 % plus rapides
|
||||
// (48 avec une carte d'aide, voir strataBuildConfig) ;
|
||||
// - --prompt-cache-root 256 : point de reprise posé à la fin du prompt système
|
||||
// (défaut 2048) : une nouvelle conversation démarre en ~0,3 s au lieu de 4-5 s.
|
||||
var strataTuning = map[string]string{
|
||||
@@ -1002,6 +1013,10 @@ func strataBuildConfig(base map[string]any, cfg map[string]string, apiKey, mode
|
||||
// de copie : 8 fils et 32 tampons (le moteur en prendrait 32 et 128)
|
||||
env["STRATA_STAGER_THREADS"] = "8"
|
||||
env["STRATA_STAGER_RING"] = "32"
|
||||
// sa VRAM libre réservée : 640 Mio (défaut 1024) = ~230 experts de plus
|
||||
// hors RAM, l'encodeur d'images y tourne encore ; le moteur refuse moins
|
||||
// de 512
|
||||
env["STRATA_REMOTE_DROP_RESERVE_MIB"] = "640"
|
||||
case "arena":
|
||||
// experts.bin mappé tel quel (variante mesurée par AJEAN), sans part PCIe :
|
||||
// le mappage n'en donne pas l'adresse GPU.
|
||||
@@ -1017,8 +1032,22 @@ func strataBuildConfig(base map[string]any, cfg map[string]string, apiKey, mode
|
||||
k, v, _ := strings.Cut(kv, "=")
|
||||
env[k] = v
|
||||
}
|
||||
if hasHelper {
|
||||
// Lecture d'un prompt (moteur 1.1) : les experts que la carte d'aide garde
|
||||
// sont calculés par elle au lieu d'être recopiés vers la principale par son
|
||||
// lien PCIe (le chemin passe par la source « helper ») ; le chemin par blocs
|
||||
// coûte alors moins cher, les ajouts courts n'en sont exclus que sous 48
|
||||
// jetons. Mesuré par AJEAN : 100 nouveaux jetons 1,19 -> 0,85 s, 200 :
|
||||
// 1,96 -> 1,12 s.
|
||||
env["STRATA_PREFILL_HELPER_SOURCE"] = "1"
|
||||
args = strataSetArg(args, "--short-read", "48")
|
||||
}
|
||||
out["env"] = env
|
||||
if ctx := strings.TrimSpace(cfg["CTX"]); ctx != "" {
|
||||
// hors RAM, le cache KV verrouillé au-delà de strataDropMaxCtx ne tient plus
|
||||
if n, err := strconv.Atoi(ctx); err == nil && n > strataDropMaxCtx && env["STRATA_REMOTE_DROP"] == "1" {
|
||||
ctx = strconv.Itoa(strataDropMaxCtx)
|
||||
}
|
||||
args = strataSetArg(args, "--max-context", ctx)
|
||||
}
|
||||
// réglages imposés par le preset (sinon : ceux de l'installeur)
|
||||
@@ -1184,17 +1213,99 @@ func strataPreflight(cfg map[string]string) error {
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return fmt.Errorf("configuration de Strata introuvable : %s — réinstalle le modèle", path)
|
||||
}
|
||||
py := filepath.Join(filepath.Dir(path), ".venv", "bin", "python")
|
||||
py := strataVenvPython(filepath.Dir(path))
|
||||
if _, err := os.Stat(py); err != nil {
|
||||
return fmt.Errorf("environnement Python de Strata absent (%s) : réinstalle le modèle", py)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// strataVenvPython : le Python de l'environnement de Strata, dans ses sources.
|
||||
func strataVenvPython(srcDir string) string { return filepath.Join(srcDir, ".venv", "bin", "python") }
|
||||
|
||||
// strataMigrate : un preset installé par une version précédente du paquet
|
||||
// (STRATA_CONFIG dans strataHome()/ajean-moe-<ancienne>) passe à la version
|
||||
// courante au lancement, sans réinstaller : les modèles et packs (data/)
|
||||
// servent tels quels. Les sources de la version courante sont posées (~340 Mo
|
||||
// avec le moteur), l'environnement Python de l'ancienne est repris par un lien
|
||||
// quand les dépendances n'ont pas changé, le moteur compilé est installé par
|
||||
// strataEnsureEngine, la config de l'installeur est recopiée avec ses chemins
|
||||
// réécrits, et les presets qui la citaient comme la config vivante pointent sur
|
||||
// la nouvelle. En cas d'échec rien n'est réécrit : l'ancienne version continue
|
||||
// de tourner. Repris d'AJEAN (moeMigrate, AJEAN MoE 1.1).
|
||||
func strataMigrate(cfg map[string]string) error {
|
||||
old := strings.TrimSpace(cfg["STRATA_CONFIG"])
|
||||
oldDir := filepath.Dir(old)
|
||||
newDir := strataSrcDir()
|
||||
if old == "" || oldDir == newDir || filepath.Dir(oldDir) != strataHome() || !strings.HasPrefix(filepath.Base(oldDir), "ajean-moe-") {
|
||||
return nil
|
||||
}
|
||||
newPath := filepath.Join(newDir, filepath.Base(old))
|
||||
if !isFile(newPath) {
|
||||
raw, err := os.ReadFile(old)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isFile(filepath.Join(newDir, "setup.py")) {
|
||||
src, err := strataFetch(strataSrcAsset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := extractArchive(src, strataHome()); err != nil {
|
||||
return fmt.Errorf("décompression : %w", err)
|
||||
}
|
||||
}
|
||||
venv := filepath.Join(newDir, ".venv")
|
||||
if _, err := os.Lstat(venv); err != nil {
|
||||
a, _ := os.ReadFile(filepath.Join(oldDir, "requirements.txt"))
|
||||
b, _ := os.ReadFile(filepath.Join(newDir, "requirements.txt"))
|
||||
if len(a) == 0 || string(a) != string(b) || !isFile(strataVenvPython(oldDir)) {
|
||||
return fmt.Errorf("dépendances Python changées : réinstalle le modèle depuis Paramètres → Moteur → Strata")
|
||||
}
|
||||
if err := os.Symlink(filepath.Join(oldDir, ".venv"), venv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Join(newDir, "engine-cuda12"), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := strataEnsureEngine(); err != nil {
|
||||
return err
|
||||
}
|
||||
body := strings.ReplaceAll(string(raw), oldDir+string(os.PathSeparator), newDir+string(os.PathSeparator))
|
||||
if err := os.WriteFile(newPath+".new", []byte(body), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Rename(newPath+".new", newPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// les presets qui citent l'ancienne config, puis la config vivante (les deux
|
||||
// changent ensemble : l'empreinte du preset actif reste celle de la config)
|
||||
if list, _ := filepath.Glob(filepath.Join(presetsDir(), "*.env")); len(list) > 0 {
|
||||
for _, p := range list {
|
||||
b, err := os.ReadFile(p)
|
||||
if err != nil || !strings.Contains(string(b), "STRATA_CONFIG="+old+"\n") {
|
||||
continue
|
||||
}
|
||||
_ = os.WriteFile(p, []byte(strings.ReplaceAll(string(b), "STRATA_CONFIG="+old+"\n", "STRATA_CONFIG="+newPath+"\n")), 0o644)
|
||||
}
|
||||
}
|
||||
if err := SetConfigKey("STRATA_CONFIG", newPath); err != nil {
|
||||
return err
|
||||
}
|
||||
cfg["STRATA_CONFIG"] = newPath
|
||||
fmt.Fprintf(os.Stderr, "[loki serve] paquet AJEAN MoE %s : installation reprise depuis %s\n", strataVersion, filepath.Base(oldDir))
|
||||
return nil
|
||||
}
|
||||
|
||||
// serveStrata : la branche Strata de `loki serve`. Écrit la config finale à
|
||||
// côté de celle de l'installeur puis remplace le process par le serveur de
|
||||
// Strata (comme pour llama-server : le superviseur suit directement le moteur).
|
||||
func serveStrata(cfg map[string]string) error {
|
||||
if err := strataMigrate(cfg); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "[loki serve] passage au paquet AJEAN MoE %s impossible (%v) : la version installée reste utilisée\n", strataVersion, err)
|
||||
}
|
||||
if err := strataPreflight(cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -1223,7 +1334,7 @@ func serveStrata(cfg map[string]string) error {
|
||||
return err
|
||||
}
|
||||
srcDir := filepath.Dir(path)
|
||||
py := filepath.Join(srcDir, ".venv", "bin", "python")
|
||||
py := strataVenvPython(srcDir)
|
||||
tag := strataConfigTag(path)
|
||||
final["log"] = filepath.Join(strataHome(), "strata-"+tag+".log")
|
||||
out := filepath.Join(strataHome(), "loki-strata-"+tag+".json")
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
package loki
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Moteur 1.1 : avec une carte d'aide, la lecture d'un prompt passe par elle
|
||||
// (source « helper ») et le chemin direct ne garde que les ajouts sous 48 jetons.
|
||||
func TestStrataBuildConfigHelperPrompt(t *testing.T) {
|
||||
base := map[string]any{"args": []any{"--pack", "/p"}}
|
||||
out, _ := strataBuildConfig(base, map[string]string{"STRATA_HELPER_GPU": "0"}, "", "ram")
|
||||
if argAfter(strataArgs(t, out), "--short-read") != "48" || out["env"].(map[string]any)["STRATA_PREFILL_HELPER_SOURCE"] != "1" {
|
||||
t.Errorf("carte d'aide : lecture courte et source d'aide attendues : %v %v", strataArgs(t, out), out["env"])
|
||||
}
|
||||
// carte d'aide coupée ou absente : réglages d'avant
|
||||
for _, cfg := range []map[string]string{{}, {"STRATA_HELPER_GPU": "0", "STRATA_HELPER": "0"}} {
|
||||
out, _ = strataBuildConfig(base, cfg, "", "ram")
|
||||
if argAfter(strataArgs(t, out), "--short-read") != "150" || out["env"].(map[string]any)["STRATA_PREFILL_HELPER_SOURCE"] != nil {
|
||||
t.Errorf("une carte (%v) : %v %v", cfg, strataArgs(t, out), out["env"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mode hors RAM : réserve de VRAM de la carte d'aide abaissée, contexte plafonné.
|
||||
func TestStrataBuildConfigDropReserveAndCtx(t *testing.T) {
|
||||
base := map[string]any{"args": []any{"--pack", "/p"}, "env": map[string]any{}}
|
||||
cfg := map[string]string{"STRATA_HELPER_GPU": "0", "CTX": "167936"}
|
||||
out, _ := strataBuildConfig(base, cfg, "", "drop")
|
||||
if out["env"].(map[string]any)["STRATA_REMOTE_DROP_RESERVE_MIB"] != "640" {
|
||||
t.Errorf("réserve de la carte d'aide : %v", out["env"])
|
||||
}
|
||||
if got := argAfter(strataArgs(t, out), "--max-context"); got != "131072" {
|
||||
t.Errorf("contexte hors RAM non plafonné : %s", got)
|
||||
}
|
||||
// hors du mode hors RAM : le contexte demandé
|
||||
for _, mode := range []string{"ram", "arena", "disk"} {
|
||||
out, _ = strataBuildConfig(base, cfg, "", mode)
|
||||
if got := argAfter(strataArgs(t, out), "--max-context"); got != "167936" {
|
||||
t.Errorf("%s : contexte plafonné sans mode hors RAM : %s", mode, got)
|
||||
}
|
||||
if out["env"].(map[string]any)["STRATA_REMOTE_DROP_RESERVE_MIB"] != nil {
|
||||
t.Errorf("%s : réserve du mode hors RAM posée : %v", mode, out["env"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Un modèle installé avec le paquet 1.0 passe au paquet courant à son premier
|
||||
// lancement, sans réinstallation.
|
||||
func TestStrataMigrate(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("lien symbolique : Strata ne tourne que sous Linux")
|
||||
}
|
||||
home := t.TempDir()
|
||||
t.Setenv("LOKI_HOME", home)
|
||||
oldDir := filepath.Join(strataHome(), "ajean-moe-1.0")
|
||||
newDir := strataSrcDir()
|
||||
for _, d := range []string{filepath.Join(oldDir, ".venv", "bin"), filepath.Join(newDir, "engine-cuda12"), presetsDir()} {
|
||||
_ = os.MkdirAll(d, 0o755)
|
||||
}
|
||||
_ = os.WriteFile(strataVenvPython(oldDir), []byte("#!/bin/sh\n"), 0o755)
|
||||
for _, d := range []string{oldDir, newDir} {
|
||||
_ = os.WriteFile(filepath.Join(d, "requirements.txt"), []byte("numpy\n"), 0o644)
|
||||
}
|
||||
_ = os.WriteFile(filepath.Join(newDir, "setup.py"), []byte(""), 0o644)
|
||||
_ = os.WriteFile(strataEngineMarker(), []byte(strataEngineAsset+"\n"), 0o644)
|
||||
old := filepath.Join(oldDir, "strata-swift-iq3_xxs.json")
|
||||
_ = os.WriteFile(old, []byte(`{"exe": "`+filepath.Join(oldDir, "engine-cuda12", "strata")+`", "args": []}`), 0o644)
|
||||
preset := filepath.Join(presetsDir(), "P.env")
|
||||
_ = os.WriteFile(preset, []byte("ENGINE=strata\nSTRATA_CONFIG="+old+"\nCTX=1\n"), 0o644)
|
||||
other := filepath.Join(presetsDir(), "L.env")
|
||||
_ = os.WriteFile(other, []byte("MODEL=/m.gguf\n"), 0o644)
|
||||
if err := SetConfigKey("STRATA_CONFIG", old); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cfg := map[string]string{"ENGINE": "strata", "STRATA_CONFIG": old}
|
||||
if err := strataMigrate(cfg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := filepath.Join(newDir, "strata-swift-iq3_xxs.json")
|
||||
if cfg["STRATA_CONFIG"] != want || ReadConfig()["STRATA_CONFIG"] != want {
|
||||
t.Fatalf("config vivante : %q", cfg["STRATA_CONFIG"])
|
||||
}
|
||||
b, _ := os.ReadFile(want)
|
||||
if strings.Contains(string(b), oldDir) || !strings.Contains(string(b), filepath.Join(newDir, "engine-cuda12")) {
|
||||
t.Errorf("chemins non réécrits : %s", b)
|
||||
}
|
||||
if p, _ := os.ReadFile(preset); !strings.Contains(string(p), "STRATA_CONFIG="+want+"\n") {
|
||||
t.Errorf("preset non réécrit : %s", p)
|
||||
}
|
||||
if p, _ := os.ReadFile(other); string(p) != "MODEL=/m.gguf\n" {
|
||||
t.Errorf("preset d'un autre moteur touché : %s", p)
|
||||
}
|
||||
if !isFile(strataVenvPython(newDir)) {
|
||||
t.Error("environnement Python non repris")
|
||||
}
|
||||
// déjà à jour : rien à faire
|
||||
if err := strataMigrate(cfg); err != nil || cfg["STRATA_CONFIG"] != want {
|
||||
t.Errorf("seconde passe : %v %q", err, cfg["STRATA_CONFIG"])
|
||||
}
|
||||
}
|
||||
|
||||
// Dépendances Python changées : rien n'est réécrit, l'ancienne version tourne.
|
||||
func TestStrataMigrateRequirementsChanged(t *testing.T) {
|
||||
home := t.TempDir()
|
||||
t.Setenv("LOKI_HOME", home)
|
||||
oldDir := filepath.Join(strataHome(), "ajean-moe-1.0")
|
||||
newDir := strataSrcDir()
|
||||
for _, d := range []string{filepath.Join(oldDir, ".venv", "bin"), newDir} {
|
||||
_ = os.MkdirAll(d, 0o755)
|
||||
}
|
||||
_ = os.WriteFile(strataVenvPython(oldDir), []byte("#!/bin/sh\n"), 0o755)
|
||||
_ = os.WriteFile(filepath.Join(oldDir, "requirements.txt"), []byte("numpy\n"), 0o644)
|
||||
_ = os.WriteFile(filepath.Join(newDir, "requirements.txt"), []byte("numpy\ntorch\n"), 0o644)
|
||||
_ = os.WriteFile(filepath.Join(newDir, "setup.py"), []byte(""), 0o644)
|
||||
old := filepath.Join(oldDir, "strata-iq3_xxs.json")
|
||||
_ = os.WriteFile(old, []byte(`{"args": []}`), 0o644)
|
||||
cfg := map[string]string{"STRATA_CONFIG": old}
|
||||
if err := strataMigrate(cfg); err == nil || !strings.Contains(err.Error(), "dépendances") {
|
||||
t.Fatalf("erreur de dépendances attendue : %v", err)
|
||||
}
|
||||
if cfg["STRATA_CONFIG"] != old || isFile(filepath.Join(newDir, "strata-iq3_xxs.json")) {
|
||||
t.Errorf("config réécrite malgré l'échec : %q", cfg["STRATA_CONFIG"])
|
||||
}
|
||||
// un preset hors de strata/ (copié à la main) n'est pas touché
|
||||
cfg = map[string]string{"STRATA_CONFIG": filepath.Join(home, "ailleurs", "ajean-moe-1.0", "strata-x.json")}
|
||||
if err := strataMigrate(cfg); err != nil {
|
||||
t.Errorf("config hors de strata/ : %v", err)
|
||||
}
|
||||
}
|
||||
@@ -184,7 +184,7 @@ func TestStrataDetailsFor(t *testing.T) {
|
||||
}
|
||||
if d.KV != "fp16" || d.KVResident != "32768" || d.Spec != "3" || d.Ctx != "131072" || !d.Mmap ||
|
||||
d.MainGPU != "RTX 5060 Ti (16 Go)" || d.HelperGPU != "RTX 3070 (8 Go)" || d.VisionGPU != "RTX 3070 (8 Go)" ||
|
||||
d.ShortRead != "150" || d.CacheRoot != "256" || d.Prefill != "16384" {
|
||||
d.ShortRead != "48" || d.CacheRoot != "256" || d.Prefill != "16384" {
|
||||
t.Errorf("%+v", *d)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,13 +249,14 @@ func TestPariteStrata(t *testing.T) {
|
||||
return out
|
||||
}
|
||||
|
||||
srcDir := filepath.Base(strataSrcDir())
|
||||
src := []parityArchEntry{
|
||||
{Name: "ajean-moe-1.0/", Type: "dir", Mode: 0o755},
|
||||
{Name: "ajean-moe-1.0/setup.sh", Type: "file", Body: parityStrataSetup, Mode: 0o755},
|
||||
{Name: "ajean-moe-1.0/setup.py", Type: "file", Body: "# installeur\n", Mode: 0o644},
|
||||
{Name: "ajean-moe-1.0/serve/server.py", Type: "file", Body: "# serveur\n", Mode: 0o644},
|
||||
{Name: srcDir + "/", Type: "dir", Mode: 0o755},
|
||||
{Name: srcDir + "/setup.sh", Type: "file", Body: parityStrataSetup, Mode: 0o755},
|
||||
{Name: srcDir + "/setup.py", Type: "file", Body: "# installeur\n", Mode: 0o644},
|
||||
{Name: srcDir + "/serve/server.py", Type: "file", Body: "# serveur\n", Mode: 0o644},
|
||||
}
|
||||
goodRel := parityStrataRel{Src: src, Engine: "moteur strata 1.0"}
|
||||
goodRel := parityStrataRel{Src: src, Engine: "moteur strata " + strataVersion}
|
||||
mem47 := "MemTotal: 49283072 kB\nMemFree: 1000000 kB\nMemAvailable: 41943040 kB\n"
|
||||
mem64 := "MemTotal: 67108864 kB\nMemAvailable: 65011712 kB\n"
|
||||
mem16 := "MemTotal: 16777216 kB\nMemAvailable: 12582912 kB\n"
|
||||
@@ -393,42 +394,47 @@ func TestPariteStrata(t *testing.T) {
|
||||
Body: `{"family":"qwen","quant":"IQ3_S"}`, Wait: true},
|
||||
{Name: "release introuvable", Meminfo: mem47, Release: &parityStrataRel{Status: 404, Src: src, Engine: "x"},
|
||||
Method: "POST", Path: "/api/strata/install", Body: `{"family":"swift","quant":"IQ3_XXS"}`, Wait: true},
|
||||
{Name: "moteur altéré", Release: &parityStrataRel{Src: src, Engine: "moteur strata 1.0", BadSHA: true},
|
||||
{Name: "moteur altéré", Release: &parityStrataRel{Src: src, Engine: "moteur strata " + strataVersion, BadSHA: true},
|
||||
Method: "POST", Path: "/api/strata/install", Body: `{"family":"swift","quant":"IQ3_XXS"}`, Wait: true},
|
||||
{Name: "installation", Release: &goodRel, Method: "POST", Path: "/api/strata/install",
|
||||
Body: `{"family":"swift","quant":"IQ3_XXS"}`, Wait: true},
|
||||
{Name: "après l'installation", Method: "GET", Path: "/api/strata"},
|
||||
{Name: "mode lancé connu, modèles inactifs", State: map[string]string{"strata_experts_mode": "drop"}, Files: map[string]string{
|
||||
"presets/STRATA FLASH NEXT CLASSIQUE IQ2_XS.env": "# NAME=Classique IQ2_XS\nENGINE=strata\nSTRATA_CONFIG={{HOME}}/strata/ajean-moe-1.0/strata-swift-iq3_xxs.json\n" +
|
||||
"presets/STRATA FLASH NEXT CLASSIQUE IQ2_XS.env": "# NAME=Classique IQ2_XS\nENGINE=strata\nSTRATA_CONFIG={{HOME}}/strata/" + srcDir + "/strata-swift-iq3_xxs.json\n" +
|
||||
"STRATA_MAIN_GPU=1\nSTRATA_HELPER_GPU=-1\nSTRATA_EXPERTS=disk\n",
|
||||
"presets/STRATA FLASH NEXT CLASSIQUE Q2_0.env": "ENGINE=moe\nSTRATA_CONFIG={{HOME}}/strata/ajean-moe-1.0/strata-swift-iq3_xxs.json\n" +
|
||||
"presets/STRATA FLASH NEXT CLASSIQUE Q2_0.env": "ENGINE=moe\nSTRATA_CONFIG={{HOME}}/strata/" + srcDir + "/strata-swift-iq3_xxs.json\n" +
|
||||
"STRATA_MAIN_GPU=0\nSTRATA_HELPER_GPU=1\nSTRATA_HELPER=0\nSTRATA_VISION=0\nSTRATA_EXPERTS=ram\n",
|
||||
}, Method: "GET", Path: "/api/strata"},
|
||||
{Name: "experts.bin et moteur du paquet", Files: map[string]string{
|
||||
"strata/data/packs/swift-iq3_xxs/experts.bin": "x",
|
||||
}, State: map[string]string{"strata_experts_mode": ""}, Method: "GET", Path: "/api/strata"},
|
||||
{Name: "RAM juste sous le seuil du mode hors RAM", Meminfo: "MemTotal: 49283072 kB\nMemAvailable: 43164063 kB\n",
|
||||
{Name: "RAM juste sous le seuil du mode hors RAM", Meminfo: "MemTotal: 49283072 kB\nMemAvailable: 44140625 kB\n",
|
||||
Method: "GET", Path: "/api/strata"},
|
||||
{Name: "RAM au-dessus du seuil du mode hors RAM", Meminfo: "MemTotal: 49283072 kB\nMemAvailable: 43457032 kB\n",
|
||||
{Name: "RAM au-dessus du seuil du mode hors RAM", Meminfo: "MemTotal: 49283072 kB\nMemAvailable: 44433594 kB\n",
|
||||
Method: "GET", Path: "/api/strata"},
|
||||
{Name: "contexte plafonné en mode hors RAM", Files: map[string]string{
|
||||
"presets/STRATA FLASH NEXT SWIFT 1.5 IQ3_XXS.env": "# NAME=Qwen3.8 Flash Next Swift 1.5 IQ3_XXS (Strata)\nENGINE=strata\n" +
|
||||
"STRATA_CONFIG={{HOME}}/strata/" + srcDir + "/strata-swift-iq3_xxs.json\nSTRATA_MAIN_GPU=1\nSTRATA_HELPER_GPU=0\n" +
|
||||
"STRATA_VISION=1\nSTRATA_EXPERTS=auto\nSTRATA_DROP=1\nSTRATA_KV=fp16\nSTRATA_KV_RESIDENT=32768\nSTRATA_SPEC=3\nCTX=196608\nREASONING=off\n",
|
||||
}, Method: "GET", Path: "/api/strata"},
|
||||
{Name: "mode hors RAM coupé dans le preset", Files: map[string]string{
|
||||
"presets/STRATA FLASH NEXT SWIFT 1.5 IQ3_XXS.env": "# NAME=Qwen3.8 Flash Next Swift 1.5 IQ3_XXS (Strata)\nENGINE=strata\n" +
|
||||
"STRATA_CONFIG={{HOME}}/strata/ajean-moe-1.0/strata-swift-iq3_xxs.json\nSTRATA_MAIN_GPU=1\nSTRATA_HELPER_GPU=0\n" +
|
||||
"STRATA_CONFIG={{HOME}}/strata/" + srcDir + "/strata-swift-iq3_xxs.json\nSTRATA_MAIN_GPU=1\nSTRATA_HELPER_GPU=0\n" +
|
||||
"STRATA_VISION=1\nSTRATA_EXPERTS=auto\nSTRATA_DROP=0\nSTRATA_KV=fp16\nSTRATA_KV_RESIDENT=32768\nSTRATA_SPEC=3\nCTX=131072\nREASONING=off\n",
|
||||
}, Method: "GET", Path: "/api/strata"},
|
||||
{Name: "moteur d'un autre paquet", Meminfo: mem47, Files: map[string]string{
|
||||
"strata/ajean-moe-1.0/engine-cuda12/.loki-engine": "ajean-moe-engine-0.9-linux-x64-cuda12.zip\n",
|
||||
"strata/" + srcDir + "/engine-cuda12/.loki-engine": "ajean-moe-engine-0.9-linux-x64-cuda12.zip\n",
|
||||
}, Method: "GET", Path: "/api/strata"},
|
||||
{Name: "réinstallation, moteur téléchargé périmé", Files: map[string]string{
|
||||
"strata/dl/ajean-moe-engine-1.0-linux-x64-cuda12.zip": "ancien moteur",
|
||||
"strata/dl/" + strataEngineAsset: "ancien moteur",
|
||||
}, Method: "POST", Path: "/api/strata/install", Body: `{"family":"swift","quant":"IQ3_XXS"}`, Wait: true},
|
||||
{Name: "installeur en échec", Method: "POST", Path: "/api/strata/install", Body: `{"family":"qwen","quant":"Q2_0"}`, Wait: true},
|
||||
{Name: "installeur sans configuration", Method: "POST", Path: "/api/strata/install", Body: `{"family":"qwen","quant":"IQ2_XS"}`, Wait: true},
|
||||
{Name: "configuration de lancement disparue", Files: map[string]string{
|
||||
"strata/ajean-moe-1.0/strata-swift-iq3_xxs.json": "-",
|
||||
"strata/" + srcDir + "/strata-swift-iq3_xxs.json": "-",
|
||||
}, Method: "GET", Path: "/api/strata"},
|
||||
{Name: "configuration de lancement illisible", Files: map[string]string{
|
||||
"strata/ajean-moe-1.0/strata-swift-iq3_xxs.json": "[1]",
|
||||
"strata/" + srcDir + "/strata-swift-iq3_xxs.json": "[1]",
|
||||
}, Method: "GET", Path: "/api/strata"},
|
||||
} {
|
||||
run(st)
|
||||
|
||||
@@ -9328,7 +9328,9 @@ function strataRenderDetails(fit){
|
||||
['Prédiction (MTP)', d.spec+' jetons'],
|
||||
['Experts hors GPU', (d.mode_label || (d.mmap ? 'lus depuis le disque (mmap)' : 'chargés en RAM'))
|
||||
+ (fit.active ? ' — dernier lancement' : ' — selon la RAM libre maintenant')],
|
||||
['Lecture des prompts', 'blocs de '+k(d.prefill)+', lecture directe sous '+d.short_read+' jetons'],
|
||||
// paquet 1.1 : la carte d'appoint calcule ses experts à la lecture d'un prompt
|
||||
['Lecture des prompts', 'blocs de '+k(d.prefill)+', lecture directe sous '+d.short_read+' jetons'
|
||||
+ (d.helper_gpu && !d.split_layers ? ", experts de la carte d'appoint calculés par elle" : '')],
|
||||
["Démarrage d'une conversation", 'reprise après le prompt système (dès '+d.cache_root+' jetons)'],
|
||||
['Version du moteur', 'paquet AJEAN MoE '+d.version],
|
||||
];
|
||||
|
||||
@@ -175,7 +175,9 @@ function strataRenderDetails(fit){
|
||||
['Prédiction (MTP)', d.spec+' jetons'],
|
||||
['Experts hors GPU', (d.mode_label || (d.mmap ? 'lus depuis le disque (mmap)' : 'chargés en RAM'))
|
||||
+ (fit.active ? ' — dernier lancement' : ' — selon la RAM libre maintenant')],
|
||||
['Lecture des prompts', 'blocs de '+k(d.prefill)+', lecture directe sous '+d.short_read+' jetons'],
|
||||
// paquet 1.1 : la carte d'appoint calcule ses experts à la lecture d'un prompt
|
||||
['Lecture des prompts', 'blocs de '+k(d.prefill)+', lecture directe sous '+d.short_read+' jetons'
|
||||
+ (d.helper_gpu && !d.split_layers ? ", experts de la carte d'appoint calculés par elle" : '')],
|
||||
["Démarrage d'une conversation", 'reprise après le prompt système (dès '+d.cache_root+' jetons)'],
|
||||
['Version du moteur', 'paquet AJEAN MoE '+d.version],
|
||||
];
|
||||
|
||||
@@ -19,24 +19,27 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
use serde_json::{Map, Value, json};
|
||||
|
||||
/// Paquet figé (release moe-v1.0 d'AJEAN).
|
||||
pub const VERSION: &str = "1.0";
|
||||
pub const RELEASE_BASE: &str = "https://github.com/nathaninline/ajean/releases/download/moe-v1.0/";
|
||||
pub const SRC_ASSET: &str = "ajean-moe-src-1.0.tar.gz";
|
||||
pub const ENGINE_ASSET: &str = "ajean-moe-engine-1.0-linux-x64-cuda12.zip";
|
||||
/// Paquet figé (release moe-v1.1 d'AJEAN : experts de la carte d'aide
|
||||
/// calculés par elle à la lecture des prompts). Un modèle installé avec la
|
||||
/// 1.0 passe à la 1.1 à son premier lancement (`strataMigrate`, côté Go :
|
||||
/// `loki serve` d'un preset Strata reste au Go).
|
||||
pub const VERSION: &str = "1.1";
|
||||
pub const RELEASE_BASE: &str = "https://github.com/nathaninline/ajean/releases/download/moe-v1.1/";
|
||||
pub const SRC_ASSET: &str = "ajean-moe-src-1.1.tar.gz";
|
||||
pub const ENGINE_ASSET: &str = "ajean-moe-engine-1.1-linux-x64-cuda12.zip";
|
||||
/// Le nom sous lequel l'installeur attend le moteur (CUDA12_ASSET).
|
||||
pub const ENGINE_LOCAL: &str = "strata-linux-x64-cuda12.zip";
|
||||
|
||||
/// `strataAssetSHA`.
|
||||
/// `strataAssetSHA` (celles qu'AJEAN publie pour moe-v1.1).
|
||||
pub fn default_asset_sha() -> HashMap<String, String> {
|
||||
HashMap::from([
|
||||
(
|
||||
SRC_ASSET.to_string(),
|
||||
"5747f69426973d957e4f9894a8e3333c6ef0d6ac8565e26ddb8d36f52211cb3b".to_string(),
|
||||
"5a72a90f2182ff0ccab2bdbd7cff15598a21ad94501aa19de2b1b18e2dbc8115".to_string(),
|
||||
),
|
||||
(
|
||||
ENGINE_ASSET.to_string(),
|
||||
"b5851bc138ab32ca3ffefc16bf91c8f557e4d503503473a22f2b6c9e9b8fd34c".to_string(),
|
||||
"8c717206ee90120f967445169dc39bb11beffdad3d592c75ae08f75bec72f0d3".to_string(),
|
||||
),
|
||||
])
|
||||
}
|
||||
@@ -137,7 +140,11 @@ pub fn quant(id: &str) -> Option<Quant> {
|
||||
}
|
||||
|
||||
pub const LOW_RAM_HEADROOM_GB: f64 = 10.0;
|
||||
pub const DROP_HEADROOM_GB: f64 = 7.0;
|
||||
/// `strataDropHeadroomGB` (le moteur 1.1 prend ~1 Go de plus que la 1.0).
|
||||
pub const DROP_HEADROOM_GB: f64 = 8.0;
|
||||
/// `strataDropMaxCtx` : contexte maximal en mode hors RAM (le cache KV
|
||||
/// au-delà de la part en VRAM est verrouillé en RAM).
|
||||
pub const DROP_MAX_CTX: i64 = 131072;
|
||||
|
||||
/// `strataHelperExpertsGB`.
|
||||
pub fn helper_experts_gb(vram_gb: f64) -> f64 {
|
||||
@@ -431,6 +438,8 @@ pub fn build_config(base: &Value, cfg: &Cfg, api_key: &str, mode: &str) -> Resul
|
||||
env.insert("STRATA_REMOTE_DROP".into(), json!("1"));
|
||||
env.insert("STRATA_STAGER_THREADS".into(), json!("8"));
|
||||
env.insert("STRATA_STAGER_RING".into(), json!("32"));
|
||||
// VRAM libre réservée de la carte d'aide : 640 Mio (défaut 1024)
|
||||
env.insert("STRATA_REMOTE_DROP_RESERVE_MIB".into(), json!("640"));
|
||||
}
|
||||
"arena" => {
|
||||
args = set_arg(args, "--pcie-frac", "0");
|
||||
@@ -445,10 +454,23 @@ pub fn build_config(base: &Value, cfg: &Cfg, api_key: &str, mode: &str) -> Resul
|
||||
for (k, v) in ENV_TUNING {
|
||||
env.insert(k.into(), json!(v));
|
||||
}
|
||||
if has_helper {
|
||||
// Lecture d'un prompt (moteur 1.1) : les experts de la carte d'aide
|
||||
// sont calculés par elle (source « helper ») ; le chemin direct ne
|
||||
// garde que les ajouts sous 48 jetons.
|
||||
env.insert("STRATA_PREFILL_HELPER_SOURCE".into(), json!("1"));
|
||||
args = set_arg(args, "--short-read", "48");
|
||||
}
|
||||
let drop_on = env.get("STRATA_REMOTE_DROP").and_then(Value::as_str) == Some("1");
|
||||
out.insert("env".into(), Value::Object(env));
|
||||
let ctx = cfg_get(cfg, "CTX").trim();
|
||||
if !ctx.is_empty() {
|
||||
args = set_arg(args, "--max-context", ctx);
|
||||
// hors RAM, le cache KV verrouillé au-delà de DROP_MAX_CTX ne tient plus
|
||||
let capped = match ctx.parse::<i64>() {
|
||||
Ok(n) if n > DROP_MAX_CTX && drop_on => DROP_MAX_CTX.to_string(),
|
||||
_ => ctx.to_string(),
|
||||
};
|
||||
args = set_arg(args, "--max-context", &capped);
|
||||
}
|
||||
for (key, flag) in [
|
||||
("STRATA_KV", "--kv"),
|
||||
|
||||
@@ -369,6 +369,42 @@ fn modes_des_experts() {
|
||||
assert!(out["env"].get("STRATA_REMOTE_DROP").is_none());
|
||||
}
|
||||
|
||||
// Moteur 1.1 (`TestStrataBuildConfigHelperPrompt`).
|
||||
#[test]
|
||||
fn lecture_des_prompts_par_la_carte_d_aide() {
|
||||
let base = json!({ "args": ["--pack", "/p"] });
|
||||
let out = build_config(&base, &cfg(&[("STRATA_HELPER_GPU", "0")]), "", "ram").unwrap();
|
||||
assert_eq!(arg_after(&args_of(&out), "--short-read"), "48");
|
||||
assert_eq!(out["env"]["STRATA_PREFILL_HELPER_SOURCE"], "1");
|
||||
for c in [
|
||||
Cfg::new(),
|
||||
cfg(&[("STRATA_HELPER_GPU", "0"), ("STRATA_HELPER", "0")]),
|
||||
] {
|
||||
let out = build_config(&base, &c, "", "ram").unwrap();
|
||||
assert_eq!(arg_after(&args_of(&out), "--short-read"), "150", "{c:?}");
|
||||
assert!(out["env"].get("STRATA_PREFILL_HELPER_SOURCE").is_none());
|
||||
}
|
||||
}
|
||||
|
||||
// `TestStrataBuildConfigDropReserveAndCtx`.
|
||||
#[test]
|
||||
fn hors_ram_reserve_et_contexte() {
|
||||
let base = json!({ "args": ["--pack", "/p"], "env": {} });
|
||||
let c = cfg(&[("STRATA_HELPER_GPU", "0"), ("CTX", "167936")]);
|
||||
let out = build_config(&base, &c, "", "drop").unwrap();
|
||||
assert_eq!(out["env"]["STRATA_REMOTE_DROP_RESERVE_MIB"], "640");
|
||||
assert_eq!(arg_after(&args_of(&out), "--max-context"), "131072");
|
||||
for mode in ["ram", "arena", "disk"] {
|
||||
let out = build_config(&base, &c, "", mode).unwrap();
|
||||
assert_eq!(
|
||||
arg_after(&args_of(&out), "--max-context"),
|
||||
"167936",
|
||||
"{mode}"
|
||||
);
|
||||
assert!(out["env"].get("STRATA_REMOTE_DROP_RESERVE_MIB").is_none());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reglages_des_experts() {
|
||||
let input = "ENGINE=strata\nSTRATA_EXPERTS=auto\n";
|
||||
|
||||
@@ -304,7 +304,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -615,7 +615,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -1066,7 +1066,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -1314,7 +1314,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -1686,8 +1686,8 @@
|
||||
"predicted_ms": 81920,
|
||||
"predicted_n": 4096,
|
||||
"predicted_per_second": 50,
|
||||
"prompt_ms": 16403,
|
||||
"prompt_n": 32806,
|
||||
"prompt_ms": 16401.5,
|
||||
"prompt_n": 32803,
|
||||
"prompt_per_second": 2000,
|
||||
"protocol": 2
|
||||
},
|
||||
@@ -1759,7 +1759,7 @@
|
||||
"max_tokens": 4096,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<131209 octets a079a2b6a1db>",
|
||||
"content": "<131199 octets aa7e053a18e5>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -1790,8 +1790,8 @@
|
||||
"predicted_ms": 81920,
|
||||
"predicted_n": 4096,
|
||||
"predicted_per_second": 50,
|
||||
"prompt_ms": 16403,
|
||||
"prompt_n": 32806,
|
||||
"prompt_ms": 16401.5,
|
||||
"prompt_n": 32803,
|
||||
"prompt_per_second": 2000,
|
||||
"protocol": 2
|
||||
}
|
||||
@@ -1813,8 +1813,8 @@
|
||||
"predicted_ms": 81920,
|
||||
"predicted_n": 4096,
|
||||
"predicted_per_second": 50,
|
||||
"prompt_ms": 16403,
|
||||
"prompt_n": 32806,
|
||||
"prompt_ms": 16401.5,
|
||||
"prompt_n": 32803,
|
||||
"prompt_per_second": 2000,
|
||||
"protocol": 2
|
||||
}
|
||||
@@ -2020,8 +2020,8 @@
|
||||
"predicted_ms": 320,
|
||||
"predicted_n": 16,
|
||||
"predicted_per_second": 50,
|
||||
"prompt_ms": 470,
|
||||
"prompt_n": 940,
|
||||
"prompt_ms": 469.5,
|
||||
"prompt_n": 939,
|
||||
"prompt_per_second": 2000,
|
||||
"protocol": 2
|
||||
},
|
||||
@@ -2093,7 +2093,7 @@
|
||||
"max_tokens": 16,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<3745 octets 5578a8f2779c>",
|
||||
"content": "<3740 octets 48e62bdc3898>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -2124,8 +2124,8 @@
|
||||
"predicted_ms": 320,
|
||||
"predicted_n": 16,
|
||||
"predicted_per_second": 50,
|
||||
"prompt_ms": 470,
|
||||
"prompt_n": 940,
|
||||
"prompt_ms": 469.5,
|
||||
"prompt_n": 939,
|
||||
"prompt_per_second": 2000,
|
||||
"protocol": 2
|
||||
}
|
||||
@@ -2147,8 +2147,8 @@
|
||||
"predicted_ms": 320,
|
||||
"predicted_n": 16,
|
||||
"predicted_per_second": 50,
|
||||
"prompt_ms": 470,
|
||||
"prompt_n": 940,
|
||||
"prompt_ms": 469.5,
|
||||
"prompt_n": 939,
|
||||
"prompt_per_second": 2000,
|
||||
"protocol": 2
|
||||
}
|
||||
@@ -2260,7 +2260,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -2541,7 +2541,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -2693,7 +2693,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -2868,7 +2868,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -3287,7 +3287,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -3457,7 +3457,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -3652,7 +3652,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
@@ -3867,7 +3867,7 @@
|
||||
"max_tokens": 300,
|
||||
"messages": [
|
||||
{
|
||||
"content": "<8129 octets ae9cc838495d>",
|
||||
"content": "<8129 octets a3e9aa90e552>",
|
||||
"role": "user"
|
||||
}
|
||||
],
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user