refactor(go-models): add unsupported model driver defaults (#15431)

### What problem does this PR solve?

Adds a shared safe default implementation for unsupported Go
model-driver capability methods and migrates the confirmed panic-stub
providers to use it.

The Go `ModelDriver` interface requires providers to implement many
capability methods even when the provider does not support them. XunFei
had unsupported capability methods implemented as `panic("implement
me")`, Mistral still had a panic in `ParseFile`, and HuaweiCloud carried
an unreachable `panic("implement me")` after a normal chat return.

### Type of change

- [x] Refactoring


Co-authored-by: Haruko386 <tryeverypossible@163.com>
This commit is contained in:
bitloi
2026-06-03 08:16:28 -03:00
committed by GitHub
parent ae316b3415
commit 2eed0d4679
6 changed files with 142 additions and 41 deletions

View File

@@ -280,7 +280,6 @@ func (h *HuaweiCloudModel) ChatWithMessages(modelName string, messages []Message
Answer: &content,
ReasonContent: &reasonContent,
}, nil
panic("implement me")
}
func (h *HuaweiCloudModel) ChatStreamlyWithSender(modelName string, messages []Message, apiConfig *APIConfig, chatModelConfig *ChatConfig, sender func(*string, *string) error) error {

View File

@@ -609,7 +609,7 @@ func (m *MistralModel) ListModels(apiConfig *APIConfig) ([]string, error) {
// Balance is not exposed by the Mistral API, so this returns "no such method".
func (m *MistralModel) Balance(apiConfig *APIConfig) (map[string]interface{}, error) {
return nil, fmt.Errorf("no such method")
return nil, fmt.Errorf("%s, no such method", m.Name())
}
// CheckConnection runs a lightweight ListModels call to verify the API key.
@@ -624,7 +624,7 @@ func (m *MistralModel) CheckConnection(apiConfig *APIConfig) error {
// Rerank calculates similarity scores between query and documents. Mistral
// does not expose a public rerank API, so this returns "no such method".
func (m *MistralModel) Rerank(modelName *string, query string, documents []string, apiConfig *APIConfig, rerankConfig *RerankConfig) (*RerankResponse, error) {
return nil, fmt.Errorf("no such method")
return nil, fmt.Errorf("%s, no such method", m.Name())
}
// TranscribeAudio transcribe audio
@@ -731,8 +731,7 @@ func (m *MistralModel) OCRFile(modelName *string, content []byte, urls *string,
}
func (m *MistralModel) ParseFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, parseFileConfig *ParseFileConfig) (*ParseFileResponse, error) {
//TODO implement me
panic("implement me")
return nil, fmt.Errorf("%s, no such method", m.Name())
}
func (m *MistralModel) ListTasks(apiConfig *APIConfig) ([]ListTaskStatus, error) {

View File

@@ -390,6 +390,49 @@ func TestMistralRerankReturnsNoSuchMethod(t *testing.T) {
}
}
func TestMistralUnsupportedDefaultsReturnNoSuchMethod(t *testing.T) {
m := newMistralForTest("http://unused")
modelName := "mistral-large-latest"
checks := []struct {
name string
call func() error
}{
{"TranscribeAudio", func() error {
_, err := m.TranscribeAudio(&modelName, nil, &APIConfig{}, nil)
return err
}},
{"TranscribeAudioWithSender", func() error {
return m.TranscribeAudioWithSender(&modelName, nil, &APIConfig{}, nil, nil)
}},
{"AudioSpeech", func() error {
_, err := m.AudioSpeech(&modelName, nil, &APIConfig{}, nil)
return err
}},
{"AudioSpeechWithSender", func() error {
return m.AudioSpeechWithSender(&modelName, nil, &APIConfig{}, nil, nil)
}},
{"ParseFile", func() error {
_, err := m.ParseFile(&modelName, nil, nil, &APIConfig{}, nil)
return err
}},
{"ListTasks", func() error {
_, err := m.ListTasks(&APIConfig{})
return err
}},
{"ShowTask", func() error {
_, err := m.ShowTask("task-id", &APIConfig{})
return err
}},
}
for _, check := range checks {
t.Run(check.name, func(t *testing.T) {
requireNoSuchMethod(t, check.name, check.call())
})
}
}
func TestMistralEmbedHappyPath(t *testing.T) {
srv := newMistralServer(t, "/embeddings", func(t *testing.T, body map[string]interface{}, w http.ResponseWriter) {
if body["model"] != "mistral-embed" {

View File

@@ -0,0 +1,16 @@
package models
import (
"strings"
"testing"
)
func requireNoSuchMethod(t *testing.T, name string, err error) {
t.Helper()
if err == nil {
t.Fatalf("%s: expected no such method error, got nil", name)
}
if !strings.Contains(err.Error(), "no such method") {
t.Fatalf("%s: expected no such method error, got %v", name, err)
}
}

View File

@@ -51,18 +51,7 @@ func NewXunFeiModel(baseURL map[string]string, urlSuffix URLSuffix) *XunFeiModel
}
func (x *XunFeiModel) NewInstance(baseURL map[string]string) ModelDriver {
return &XunFeiModel{
BaseURL: baseURL,
URLSuffix: x.URLSuffix,
httpClient: &http.Client{
Transport: &http.Transport{
MaxIdleConns: 10,
MaxIdleConnsPerHost: 100,
IdleConnTimeout: time.Second * 90,
DisableCompression: false,
},
},
}
return NewXunFeiModel(baseURL, x.URLSuffix)
}
func (x *XunFeiModel) Name() string {
@@ -358,43 +347,35 @@ func (x *XunFeiModel) ChatStreamlyWithSender(modelName string, messages []Messag
}
func (x *XunFeiModel) Embed(modelName *string, texts []string, apiConfig *APIConfig, embeddingConfig *EmbeddingConfig) ([]EmbeddingData, error) {
//TODO implement me
panic("implement me")
return nil, fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) Rerank(modelName *string, query string, documents []string, apiConfig *APIConfig, rerankConfig *RerankConfig) (*RerankResponse, error) {
//TODO implement me
panic("implement me")
return nil, fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) TranscribeAudio(modelName *string, file *string, apiConfig *APIConfig, asrConfig *ASRConfig) (*ASRResponse, error) {
//TODO implement me
panic("implement me")
return nil, fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) TranscribeAudioWithSender(modelName *string, file *string, apiConfig *APIConfig, asrConfig *ASRConfig, sender func(*string, *string) error) error {
//TODO implement me
panic("implement me")
return fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) AudioSpeech(modelName *string, audioContent *string, apiConfig *APIConfig, ttsConfig *TTSConfig) (*TTSResponse, error) {
//TODO implement me
panic("implement me")
return nil, fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) AudioSpeechWithSender(modelName *string, audioContent *string, apiConfig *APIConfig, ttsConfig *TTSConfig, sender func(*string, *string) error) error {
//TODO implement me
panic("implement me")
return fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) OCRFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, ocrConfig *OCRConfig) (*OCRFileResponse, error) {
//TODO implement me
panic("implement me")
return nil, fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) ParseFile(modelName *string, content []byte, url *string, apiConfig *APIConfig, parseFileConfig *ParseFileConfig) (*ParseFileResponse, error) {
//TODO implement me
panic("implement me")
return nil, fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) ListModels(apiConfig *APIConfig) ([]string, error) {
@@ -457,21 +438,17 @@ func (x *XunFeiModel) ListModels(apiConfig *APIConfig) ([]string, error) {
}
func (x *XunFeiModel) Balance(apiConfig *APIConfig) (map[string]interface{}, error) {
//TODO implement me
panic("implement me")
return nil, fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) CheckConnection(apiConfig *APIConfig) error {
//TODO implement me
panic("implement me")
return fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) ListTasks(apiConfig *APIConfig) ([]ListTaskStatus, error) {
//TODO implement me
panic("implement me")
return nil, fmt.Errorf("%s, no such method", x.Name())
}
func (x *XunFeiModel) ShowTask(taskID string, apiConfig *APIConfig) (*TaskResponse, error) {
//TODO implement me
panic("implement me")
return nil, fmt.Errorf("%s, no such method", x.Name())
}

View File

@@ -0,0 +1,67 @@
package models
import "testing"
func TestXunFeiUnsupportedMethodsReturnNoSuchMethod(t *testing.T) {
driver := NewXunFeiModel(map[string]string{"default": "http://unused"}, URLSuffix{}).
NewInstance(map[string]string{"default": "http://unused"})
modelName := "spark"
text := "hello"
checks := []struct {
name string
call func() error
}{
{"Embed", func() error {
_, err := driver.Embed(&modelName, []string{text}, &APIConfig{}, nil)
return err
}},
{"Rerank", func() error {
_, err := driver.Rerank(&modelName, text, []string{text}, &APIConfig{}, nil)
return err
}},
{"TranscribeAudio", func() error {
_, err := driver.TranscribeAudio(&modelName, &text, &APIConfig{}, nil)
return err
}},
{"TranscribeAudioWithSender", func() error {
return driver.TranscribeAudioWithSender(&modelName, &text, &APIConfig{}, nil, nil)
}},
{"AudioSpeech", func() error {
_, err := driver.AudioSpeech(&modelName, &text, &APIConfig{}, nil)
return err
}},
{"AudioSpeechWithSender", func() error {
return driver.AudioSpeechWithSender(&modelName, &text, &APIConfig{}, nil, nil)
}},
{"OCRFile", func() error {
_, err := driver.OCRFile(&modelName, nil, &text, &APIConfig{}, nil)
return err
}},
{"ParseFile", func() error {
_, err := driver.ParseFile(&modelName, nil, &text, &APIConfig{}, nil)
return err
}},
{"Balance", func() error {
_, err := driver.Balance(&APIConfig{})
return err
}},
{"CheckConnection", func() error {
return driver.CheckConnection(&APIConfig{})
}},
{"ListTasks", func() error {
_, err := driver.ListTasks(&APIConfig{})
return err
}},
{"ShowTask", func() error {
_, err := driver.ShowTask("task-id", &APIConfig{})
return err
}},
}
for _, check := range checks {
t.Run(check.name, func(t *testing.T) {
requireNoSuchMethod(t, check.name, check.call())
})
}
}