fix(llm): derive aiproxy upstream model key from local_path sku (#25269)

This commit is contained in:
Zexi Li
2026-08-03 15:43:54 +08:00
committed by GitHub
parent d45131bbe0
commit 19e752f3a4
3 changed files with 91 additions and 0 deletions
+5
View File
@@ -270,6 +270,11 @@ func collectUpstreamModelKeys(ctx context.Context, userCred mcclient.TokenCreden
seen[key] = struct{}{}
keys = append(keys, key)
}
if len(keys) == 0 {
if key := UpstreamModelKeyFromLocalPathSku(llm, sku); key != "" {
keys = append(keys, key)
}
}
if len(keys) == 0 {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no mounted models on llm instance")
}
+46
View File
@@ -2,6 +2,7 @@ package models
import (
"fmt"
"path"
"strings"
"yunion.io/x/pkg/errors"
@@ -88,6 +89,51 @@ func SkuHasLocalHostPathModel(sku *SLLMSku) bool {
return hostPathsHasContainerMount(*sku.HostPaths, 0)
}
func effectiveLLMPreferredModel(llm *SLLM, sku *SLLMSku) string {
if llm != nil && llm.LLMSpec != nil {
if llm.LLMSpec.Vllm != nil {
if p := strings.TrimSpace(llm.LLMSpec.Vllm.PreferredModel); p != "" {
return p
}
}
if llm.LLMSpec.SGLang != nil {
if p := strings.TrimSpace(llm.LLMSpec.SGLang.PreferredModel); p != "" {
return p
}
}
}
if sku != nil && sku.LLMSpec != nil {
if sku.LLMSpec.Vllm != nil {
if p := strings.TrimSpace(sku.LLMSpec.Vllm.PreferredModel); p != "" {
return p
}
}
if sku.LLMSpec.SGLang != nil {
if p := strings.TrimSpace(sku.LLMSpec.SGLang.PreferredModel); p != "" {
return p
}
}
}
return ""
}
// UpstreamModelKeyFromLocalPathSku returns the served model name vLLM/SGLang expose
// for a local_path SKU (basename of the selected container model mount path).
func UpstreamModelKeyFromLocalPathSku(llm *SLLM, sku *SLLMSku) string {
if !SkuHasLocalHostPathModel(sku) {
return ""
}
preferred := effectiveLLMPreferredModel(llm, sku)
modelPath := PickContainerModelMountPath(CollectContainerModelMountPaths(llm, sku), preferred)
if modelPath != "" {
return path.Base(modelPath)
}
if lp := strings.TrimSpace(sku.LocalPath); lp != "" {
return path.Base(lp)
}
return ""
}
// ValidateLocalPathHamiDevicesRequireMemoryMb requires every HAMi device to set
// memory_mb for local_path SKUs (no InstantModel VRAM estimate available).
// Devices are normalized first so empty SharingMode (default HAMi) is treated
+40
View File
@@ -119,6 +119,46 @@ func TestSkuHasLocalHostPathModel(t *testing.T) {
}
}
func TestUpstreamModelKeyFromLocalPathSku(t *testing.T) {
hostPaths := llm.HostPaths{
{
Type: "directory",
Path: "/data/models/Qwen3-8B",
Containers: llm.ContainerHostPathRelations{
"0": {MountPath: "/data/models/huggingface/Qwen3-8B"},
},
},
}
sku := &SLLMSku{
LLMType: string(llm.LLM_CONTAINER_VLLM),
Source: llm.LLM_MODEL_SOURCE_LOCAL_PATH,
LocalPath: "/data/models/Qwen3-8B",
}
sku.HostPaths = &hostPaths
got := UpstreamModelKeyFromLocalPathSku(nil, sku)
if got != "Qwen3-8B" {
t.Fatalf("expected upstream model key Qwen3-8B, got %q", got)
}
skuWithPreferred := &SLLMSku{
LLMType: string(llm.LLM_CONTAINER_VLLM),
Source: llm.LLM_MODEL_SOURCE_LOCAL_PATH,
LocalPath: "/data/models/Qwen3-8B",
LLMSpec: &llm.LLMSpec{Vllm: &llm.LLMSpecVllm{PreferredModel: "Qwen3-8B"}},
}
skuWithPreferred.HostPaths = &hostPaths
got = UpstreamModelKeyFromLocalPathSku(nil, skuWithPreferred)
if got != "Qwen3-8B" {
t.Fatalf("expected upstream model key with preferred model, got %q", got)
}
nonLocal := &SLLMSku{LLMType: string(llm.LLM_CONTAINER_VLLM)}
if UpstreamModelKeyFromLocalPathSku(nil, nonLocal) != "" {
t.Fatal("expected empty key for non local_path sku")
}
}
func TestValidateLocalPathHamiDevicesRequireMemoryMb(t *testing.T) {
t.Run("hami without memory_mb fails", func(t *testing.T) {
devs := llm.Devices{{Model: "A100", SharingMode: "HAMI"}}