Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions pkg/hfutil/modelconfig/mistral.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"os"
"strings"
)

// MistralConfig defines the configuration for Mistral models
Expand Down Expand Up @@ -117,7 +118,7 @@ func (c *MistralConfig) GetArchitecture() string {
if len(c.Architectures) > 0 {
return c.Architectures[0]
}
return "MistralModel"
return ""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the empty string as architecture going to be handled by the downstream matcher? Does the corresponding runtime have explicit "" as architecture?

@abinggo abinggo May 10, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@YouNeedCryDear Thanks for the review. I verified the downstream handling in pkg/modelagent/config_parser.go — all usages of GetArchitecture() normalize via strings.ToLower() and use strings.Contains() for pattern matching. When architecture is "", no specific patterns match, and determineModelCapabilitiesFromHF() correctly falls through to the default ModelCapabilityTextToText at line 586. The embedding check at line 575 relies on IsEmbedding() (which is now self-contained in MistralConfig) rather than the architecture string directly, so this is safe.
This is also consistent with how BaseModelConfig, PhiConfig, and DeepSeekV3Config handle missing architectures — they all return "".

}

func (c *MistralConfig) GetModelType() string {
Expand All @@ -140,9 +141,10 @@ func (c *MistralConfig) HasVision() bool {
return false
}

// IsEmbedding returns true since this is an embedding model
// IsEmbedding returns true when the architecture is "MistralModel", which indicates
// an embedding model (e.g. intfloat/e5-mistral-7b-instruct).
func (c *MistralConfig) IsEmbedding() bool {
return true
return strings.EqualFold(c.GetArchitecture(), "MistralModel")
}

// Register the Mistral model handler
Expand Down
59 changes: 59 additions & 0 deletions pkg/hfutil/modelconfig/mistral_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,65 @@ func TestLoadModelWithMistral(t *testing.T) {
t.Logf("Mistral model parameter count via generic loader: %s", FormatParamCount(paramCount))
}

// TestMistralConfigNoArchitectures verifies that when the Architectures field
// is missing from config.json, GetArchitecture() returns an empty string rather
// than a misleading fallback like "MistralModel" which would cause the model to
// be misclassified as an embedding model by the config parser.
// Regression test for https://github.com/ome-projects/ome/issues/601
func TestMistralConfigNoArchitectures(t *testing.T) {
configPath := filepath.Join("testdata", "mistral_no_architectures.json")

config, err := LoadModelConfig(configPath)
if err != nil {
t.Fatalf("Failed to load Mistral config without architectures: %v", err)
}

// GetArchitecture must return empty string when Architectures is absent
arch := config.GetArchitecture()
if arch != "" {
t.Errorf("Expected empty architecture when Architectures field is missing, got '%s'", arch)
}

// IsEmbedding must return false for a generic Mistral model
if config.IsEmbedding() {
t.Error("Expected IsEmbedding() to return false for a generic Mistral model without explicit embedding architecture")
}

// Verify it's still recognized as a Mistral model
if config.GetModelType() != "mistral" {
t.Errorf("Expected model type 'mistral', got '%s'", config.GetModelType())
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test covers the negative case (no architectures → not embedding) but there is no counterpart for the positive case. Please add a test with a fixture that has "architectures": ["MistralModel"] set and assert:

  • GetArchitecture() == "MistralModel"
  • GetModelType() == "mistral"

That combination is what config_parser.go relies on to classify e5-mistral as EMBEDDING — it is the load-bearing path and easy to accidentally break in a future refactor. Without a test here, nothing catches a regression.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test covers the negative case (no architectures → not embedding) but there is no counterpart for the positive case. Please add a test with a fixture that has "architectures": ["MistralModel"] set and assert:

  • GetArchitecture() == "MistralModel"
  • GetModelType() == "mistral"

That combination is what config_parser.go relies on to classify e5-mistral as EMBEDDING — it is the load-bearing path and easy to accidentally break in a future refactor. Without a test here, nothing catches a regression.


// TestMistralConfigEmbedding verifies that a Mistral model with
// "architectures": ["MistralModel"] is correctly identified as an embedding
// model (e.g. intfloat/e5-mistral-7b-instruct).
// This is the load-bearing positive case for config_parser.go's EMBEDDING classification.
func TestMistralConfigEmbedding(t *testing.T) {
configPath := filepath.Join("testdata", "mistral_embedding.json")

config, err := LoadModelConfig(configPath)
if err != nil {
t.Fatalf("Failed to load Mistral embedding config: %v", err)
}

// GetArchitecture must return "MistralModel"
arch := config.GetArchitecture()
if arch != "MistralModel" {
t.Errorf("Expected architecture 'MistralModel', got '%s'", arch)
}

// GetModelType must return "mistral"
if config.GetModelType() != "mistral" {
t.Errorf("Expected model type 'mistral', got '%s'", config.GetModelType())
}

// IsEmbedding must return true for MistralModel architecture
if !config.IsEmbedding() {
t.Error("Expected IsEmbedding() to return true for a model with 'MistralModel' architecture")
}
}

func TestMistralInstructConfig(t *testing.T) {
configPath := filepath.Join("testdata", "mistral_7b_instruct.json")

Expand Down
22 changes: 22 additions & 0 deletions pkg/hfutil/modelconfig/testdata/mistral_embedding.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"architectures": ["MistralModel"],
"bos_token_id": 1,
"eos_token_id": 2,
"hidden_act": "silu",
"hidden_size": 4096,
"initializer_range": 0.02,
"intermediate_size": 14336,
"max_position_embeddings": 32768,
"model_type": "mistral",
"num_attention_heads": 32,
"num_hidden_layers": 32,
"num_key_value_heads": 8,
"rms_norm_eps": 1e-05,
"rope_theta": 10000.0,
"sliding_window": 4096,
"tie_word_embeddings": false,
"torch_dtype": "float16",
"transformers_version": "4.36.0",
"use_cache": true,
"vocab_size": 32000
}
21 changes: 21 additions & 0 deletions pkg/hfutil/modelconfig/testdata/mistral_no_architectures.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"bos_token_id": 1,
"eos_token_id": 2,
"hidden_act": "silu",
"hidden_size": 4096,
"initializer_range": 0.02,
"intermediate_size": 14336,
"max_position_embeddings": 32768,
"model_type": "mistral",
"num_attention_heads": 32,
"num_hidden_layers": 32,
"num_key_value_heads": 8,
"rms_norm_eps": 1e-05,
"rope_theta": 10000.0,
"sliding_window": 4096,
"tie_word_embeddings": false,
"torch_dtype": "bfloat16",
"transformers_version": "4.34.0.dev0",
"use_cache": true,
"vocab_size": 32000
}
Loading