Fix Qwen session tool calls and expose thinking compatibility
Publish documentation / publish (push) Successful in 30s
Publish documentation / publish (push) Successful in 30s
This commit is contained in:
@@ -28,6 +28,38 @@ func TestLoadAcceptsInstallationModelCatalog(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadQwenThinkingCompatibility(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
name, format string
|
||||
reasoning bool
|
||||
wantError bool
|
||||
}{
|
||||
{"vllm template", "qwen-chat-template", true, false},
|
||||
{"top level Qwen", "qwen", true, false},
|
||||
{"unknown format", "qwen-typo", true, true},
|
||||
{"thinking disabled in model capabilities", "qwen-chat-template", false, true},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
path, _, _, _ := writeInstallation(t, "local")
|
||||
reasoning := "false"
|
||||
if test.reasoning {
|
||||
reasoning = "true"
|
||||
}
|
||||
catalog := strings.Replace(validModelCatalogYAML(), " contextWindow: 32768",
|
||||
" reasoning: "+reasoning+"\n compatibility:\n thinkingFormat: "+test.format+"\n contextWindow: 32768", 1)
|
||||
rewriteInstallationCatalog(t, path, catalog)
|
||||
_, err := Load(path)
|
||||
if test.wantError {
|
||||
if err == nil || !strings.Contains(err.Error(), "thinkingFormat") {
|
||||
t.Fatalf("Load() error = %v, want thinkingFormat error", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
t.Fatalf("Load() error = %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadAcceptsSharedDeepSeekBuiltinWithBundleAuthentication(t *testing.T) {
|
||||
path, _, envFile, _ := writeInstallation(t, "local")
|
||||
catalog := strings.Replace(validModelCatalogYAML(), "interaction: zai/glm-5.3", "interaction: deepseek/deepseek-v4-pro", 1)
|
||||
|
||||
@@ -90,6 +90,7 @@ type ModelCompatibility struct {
|
||||
SupportsReasoningEffort bool `yaml:"supportsReasoningEffort" json:"supportsReasoningEffort"`
|
||||
SupportsStore bool `yaml:"supportsStore" json:"supportsStore"`
|
||||
MaxTokensField string `yaml:"maxTokensField" json:"maxTokensField,omitempty"`
|
||||
ThinkingFormat string `yaml:"thinkingFormat,omitempty" json:"thinkingFormat,omitempty"`
|
||||
}
|
||||
|
||||
type SessionModel struct {
|
||||
@@ -270,6 +271,15 @@ func validateCatalogProvider(id string, provider ModelProvider, hasSession, hasM
|
||||
if model.Session != nil && (model.Session.ContextWindow <= 0 || model.Session.MaxTokens <= 0) {
|
||||
return fmt.Errorf("modelCatalog model %q/%q requires contextWindow and maxTokens", id, modelID)
|
||||
}
|
||||
if model.Session != nil && model.Session.Compatibility != nil {
|
||||
format := model.Session.Compatibility.ThinkingFormat
|
||||
if format != "" && format != "qwen" && format != "qwen-chat-template" {
|
||||
return fmt.Errorf("modelCatalog model %q/%q compatibility.thinkingFormat is invalid", id, modelID)
|
||||
}
|
||||
if format != "" && !model.Session.Reasoning {
|
||||
return fmt.Errorf("modelCatalog model %q/%q compatibility.thinkingFormat requires reasoning: true", id, modelID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if provider.Session != nil {
|
||||
|
||||
@@ -97,6 +97,30 @@ func TestDeepSeekBuiltinAndMetadataShareCatalogIdentityAndSecretReference(t *tes
|
||||
}
|
||||
}
|
||||
|
||||
func TestQwenThinkingFormatSurvivesCatalogAndPiProjection(t *testing.T) {
|
||||
i := projectionFixture(t)
|
||||
model := i.ModelCatalog.Providers["local"].Models["qwen"]
|
||||
if err := json.Unmarshal([]byte(`{"reasoning":true,"contextWindow":32768,"maxTokens":8192,"compatibility":{"supportsDeveloperRole":false,"supportsReasoningEffort":false,"supportsStore":false,"maxTokensField":"max_tokens","thinkingFormat":"qwen-chat-template"}}`), model.Session); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
files, err := Render(i)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, path := range []string{CatalogFile, PiModelsFile} {
|
||||
if !bytes.Contains(files[path], []byte(`"thinkingFormat": "qwen-chat-template"`)) {
|
||||
t.Fatalf("%s dropped Qwen thinking compatibility", path)
|
||||
}
|
||||
}
|
||||
var models piModels
|
||||
if err := json.Unmarshal(files[PiModelsFile], &models); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !models.Providers["local"].Models[0].Reasoning {
|
||||
t.Fatal("Pi must know the model supports explicit thinking control")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProjectionKeepsSingleUseInventoryOutOfSharedPiSelection(t *testing.T) {
|
||||
i := projectionFixture(t)
|
||||
p := i.ModelCatalog.Providers["zai"]
|
||||
|
||||
Reference in New Issue
Block a user