mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 23:41:12 +08:00
feat(go): Add DeepSeek models and Gitee alias metadata tests (#15885)
This PR expands conf/all_models.json with DeepSeek model entries and provider aliases. Changes: - Added DeepSeek model entries across `V4`, `V3.2`, `V3.1`, `V3`, `R1`, `Coder`, `Math`, `VL`, `OCR`, `Prover`, `MoE`, and `LLM` series. - Normalized model name values to lowercase canonical IDs. - Added alias values for official DeepSeek/Hugging Face names and provider-specific names from OpenRouter, VolcEngine, SiliconFlow, HuaweiCloud, and QiniuCloud. - Preserved model metadata such as max_tokens, model_types, and thinking where applicable. - Added Gitee ListModels tests to verify DeepSeek aliases map back to model metadata from all_models.json. - Added an optional Gitee integration test gated by GITEE_LIST_MODELS_INTEGRATION=1. Test: /usr/local/go/bin/go clean -cache /usr/local/go/bin/go test ./internal/entity/models -run 'TestGiteeListModels(MapsAllDeepSeekAliasesToModelMetadata|KeepsOwnedBySuffixAfterAliasMetadataLookup| Integration)'
This commit is contained in:
216
internal/entity/models/gitee_test.go
Normal file
216
internal/entity/models/gitee_test.go
Normal file
@@ -0,0 +1,216 @@
|
||||
//
|
||||
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func initProviderManagerWithGiteeForTest(t *testing.T) {
|
||||
t.Helper()
|
||||
|
||||
dir := t.TempDir()
|
||||
if err := os.WriteFile(filepath.Join(dir, "gitee.json"), readProviderConfig(t, "gitee.json"), 0o600); err != nil {
|
||||
t.Fatalf("write gitee config: %v", err)
|
||||
}
|
||||
if err := InitProviderManager(dir); err != nil {
|
||||
t.Fatalf("InitProviderManager: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func newGiteeForListModelsTest(baseURL string) *GiteeModel {
|
||||
return NewGiteeModel(map[string]string{"default": baseURL}, URLSuffix{Models: "models"})
|
||||
}
|
||||
|
||||
func deepSeekAliasModelsForTest(t *testing.T) map[string]Model {
|
||||
t.Helper()
|
||||
|
||||
pm := GetProviderManager()
|
||||
if pm == nil {
|
||||
t.Fatal("provider manager is nil")
|
||||
}
|
||||
|
||||
aliasModels := map[string]Model{}
|
||||
for _, model := range pm.AllModels {
|
||||
if !strings.HasPrefix(model.Name, "deepseek-") {
|
||||
continue
|
||||
}
|
||||
for _, alias := range model.Alias {
|
||||
if alias == "" {
|
||||
continue
|
||||
}
|
||||
if existing, ok := aliasModels[alias]; ok {
|
||||
t.Fatalf("duplicate DeepSeek alias %q for %q and %q", alias, existing.Name, model.Name)
|
||||
}
|
||||
aliasModels[alias] = model
|
||||
}
|
||||
}
|
||||
if len(aliasModels) == 0 {
|
||||
t.Fatal("no DeepSeek aliases found in all_models.json")
|
||||
}
|
||||
return aliasModels
|
||||
}
|
||||
|
||||
func TestGiteeListModelsMapsAllDeepSeekAliasesToModelMetadata(t *testing.T) {
|
||||
initProviderManagerWithGiteeForTest(t)
|
||||
aliasModels := deepSeekAliasModelsForTest(t)
|
||||
aliases := make([]string, 0, len(aliasModels))
|
||||
for alias := range aliasModels {
|
||||
aliases = append(aliases, alias)
|
||||
}
|
||||
sort.Strings(aliases)
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
t.Errorf("method=%s, want GET", r.Method)
|
||||
}
|
||||
if r.URL.Path != "/models" {
|
||||
t.Errorf("path=%s, want /models", r.URL.Path)
|
||||
}
|
||||
if got := r.Header.Get("Content-Type"); got != "application/json" {
|
||||
t.Errorf("Content-Type=%q, want application/json", got)
|
||||
}
|
||||
|
||||
resp := DSModelList{
|
||||
Object: "list",
|
||||
Models: make([]DSModel, 0, len(aliases)+1),
|
||||
}
|
||||
for _, alias := range aliases {
|
||||
resp.Models = append(resp.Models, DSModel{ID: alias})
|
||||
}
|
||||
resp.Models = append(resp.Models, DSModel{ID: "unknown-model"})
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(resp); err != nil {
|
||||
t.Fatalf("encode response: %v", err)
|
||||
}
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
models, err := newGiteeForListModelsTest(srv.URL).ListModels(&APIConfig{})
|
||||
if err != nil {
|
||||
t.Fatalf("ListModels: %v", err)
|
||||
}
|
||||
if got, want := len(models), len(aliases)+1; got != want {
|
||||
t.Fatalf("len(models)=%d, want %d", got, want)
|
||||
}
|
||||
|
||||
for i, alias := range aliases {
|
||||
model := models[i]
|
||||
expected := aliasModels[alias]
|
||||
if model.Name != alias {
|
||||
t.Fatalf("models[%d].Name=%q, want %q", i, model.Name, alias)
|
||||
}
|
||||
if (model.MaxTokens == nil) != (expected.MaxTokens == nil) {
|
||||
t.Fatalf("models[%d] alias %q MaxTokens nil=%t, want nil=%t", i, alias, model.MaxTokens == nil, expected.MaxTokens == nil)
|
||||
}
|
||||
if model.MaxTokens != nil && expected.MaxTokens != nil && *model.MaxTokens != *expected.MaxTokens {
|
||||
t.Fatalf("models[%d] alias %q MaxTokens=%d, want %d", i, alias, *model.MaxTokens, *expected.MaxTokens)
|
||||
}
|
||||
if strings.Join(model.ModelTypes, ",") != strings.Join(expected.ModelTypes, ",") {
|
||||
t.Fatalf("models[%d] alias %q ModelTypes=%v, want %v", i, alias, model.ModelTypes, expected.ModelTypes)
|
||||
}
|
||||
if (model.Thinking == nil) != (expected.Thinking == nil) {
|
||||
t.Fatalf("models[%d] alias %q Thinking nil=%t, want nil=%t", i, alias, model.Thinking == nil, expected.Thinking == nil)
|
||||
}
|
||||
}
|
||||
|
||||
unknown := models[len(models)-1]
|
||||
if unknown.Name != "unknown-model" {
|
||||
t.Fatalf("unknown.Name=%q, want unknown-model", unknown.Name)
|
||||
}
|
||||
if unknown.MaxTokens != nil {
|
||||
t.Fatalf("unknown.MaxTokens=%v, want nil", *unknown.MaxTokens)
|
||||
}
|
||||
if len(unknown.ModelTypes) != 0 {
|
||||
t.Fatalf("unknown.ModelTypes=%v, want empty", unknown.ModelTypes)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGiteeListModelsKeepsOwnedBySuffixAfterAliasMetadataLookup(t *testing.T) {
|
||||
initProviderManagerWithGiteeForTest(t)
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = io.WriteString(w, `{"object":"list","data":[{"id":"deepseek/deepseek-v4-pro","owned_by":"gitee"}]}`)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
models, err := newGiteeForListModelsTest(srv.URL).ListModels(&APIConfig{})
|
||||
if err != nil {
|
||||
t.Fatalf("ListModels: %v", err)
|
||||
}
|
||||
if len(models) != 1 {
|
||||
t.Fatalf("len(models)=%d, want 1", len(models))
|
||||
}
|
||||
model := models[0]
|
||||
if model.Name != "deepseek/deepseek-v4-pro@gitee" {
|
||||
t.Fatalf("Name=%q, want deepseek/deepseek-v4-pro@gitee", model.Name)
|
||||
}
|
||||
if model.MaxTokens == nil || *model.MaxTokens != 1048576 {
|
||||
t.Fatalf("MaxTokens=%v, want 1048576", model.MaxTokens)
|
||||
}
|
||||
if len(model.ModelTypes) != 1 || model.ModelTypes[0] != "chat" {
|
||||
t.Fatalf("ModelTypes=%v, want [chat]", model.ModelTypes)
|
||||
}
|
||||
if model.Thinking == nil {
|
||||
t.Fatal("Thinking=nil, want DeepSeek V4 Pro thinking metadata")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGiteeListModelsIntegration(t *testing.T) {
|
||||
if os.Getenv("GITEE_LIST_MODELS_INTEGRATION") != "1" {
|
||||
t.Skip("set GITEE_LIST_MODELS_INTEGRATION=1 to call the real Gitee models endpoint")
|
||||
}
|
||||
|
||||
initProviderManagerWithGiteeForTest(t)
|
||||
|
||||
baseURL := os.Getenv("GITEE_BASE_URL")
|
||||
if baseURL == "" {
|
||||
baseURL = "https://api.moark.ai/v1"
|
||||
}
|
||||
apiConfig := &APIConfig{}
|
||||
if apiKey := os.Getenv("GITEE_API_KEY"); apiKey != "" {
|
||||
apiConfig.ApiKey = &apiKey
|
||||
}
|
||||
|
||||
models, err := newGiteeForListModelsTest(baseURL).ListModels(apiConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("real Gitee ListModels: %v", err)
|
||||
}
|
||||
if len(models) == 0 {
|
||||
t.Fatal("real Gitee ListModels returned no models")
|
||||
}
|
||||
|
||||
var matchedDeepSeek int
|
||||
for _, model := range models {
|
||||
if strings.Contains(strings.ToLower(model.Name), "deepseek") && len(model.ModelTypes) > 0 {
|
||||
matchedDeepSeek++
|
||||
}
|
||||
}
|
||||
if matchedDeepSeek == 0 {
|
||||
t.Fatalf("real Gitee ListModels returned %d models but none of the DeepSeek models mapped to all_models metadata: %s", len(models), fmt.Sprint(models))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user