Files
ragflow/internal/entity/models/factory.go
dripsmvcp a48bcf814d Go: implement provider: ModelScope (#15041)
Closes #15040.

ModelScope was listed unchecked in the Go-rewrite tracker #14736 and
already had an llm_factories.json entry (tags: LLM) but no Go driver, so
the new Go API server could not route ModelScope instances. The Python
side has supported it through the OpenAI-compatible base at
rag/llm/chat_model.py:618 (ModelScopeChat), which requires a
user-supplied base URL and appends /v1.

This adds:
- internal/entity/models/modelscope.go: self-hosted OpenAI-compatible
driver with chat (sync + SSE stream with idle-timeout cancellation),
list_models, and check_connection. Auth header is optional, matching the
xinference pattern, so deployments without auth and auth-enabled
deployments both work. Base URL is normalized so users can configure
either the root endpoint or the /v1 endpoint.
- internal/entity/models/modelscope_test.go: 12 tests covering name, URL
normalization, factory routing, chat happy path / auth header /
reasoning_content extraction, stream happy path / stream=false rejection
/ idle cancellation, list_models + check_connection, missing-base-URL
clear error, and the no-such-method sentinels.
- conf/models/modelscope.json: shipped config (class: "local",
url_suffix v1/chat/completions and v1/models).
- internal/entity/models/factory.go: case "modelscope" →
ModelScopeModel.
- internal/service/llm.go: ModelScope added to the selfDeployed map
alongside Ollama, Xinference, LocalAI, LM-Studio, GPUStack — the Python
side requires user-supplied URL with no default, so the Go side
classifies it the same way.

Follow-on issues will add Embed and Rerank, in line with how Novita,
NVIDIA, TogetherAI, and other providers landed method-by-method.

---------

Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-26 18:18:46 +08:00

154 lines
5.0 KiB
Go

//
// 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 (
"strings"
)
// ModelFactory creates ModelDriver instances based on provider name
type ModelFactory struct {
}
// NewModelFactory creates a new ModelFactory
func NewModelFactory() *ModelFactory {
return &ModelFactory{}
}
// CreateModelDriver creates a ModelDriver for the given provider and model
func (f *ModelFactory) CreateModelDriver(providerName string, baseURL map[string]string, urlSuffix URLSuffix) (ModelDriver, error) {
providerLower := strings.ToLower(providerName)
switch providerLower {
case "anthropic":
return NewAnthropicModel(baseURL, urlSuffix), nil
case "zhipu-ai":
return NewZhipuAIModel(baseURL, urlSuffix), nil
case "deepseek":
return NewDeepSeekModel(baseURL, urlSuffix), nil
case "moonshot":
return NewMoonshotModel(baseURL, urlSuffix), nil
case "minimax":
return NewMinimaxModel(baseURL, urlSuffix), nil
case "gitee":
return NewGiteeModel(baseURL, urlSuffix), nil
case "siliconflow":
return NewSiliconflowModel(baseURL, urlSuffix), nil
case "google":
return NewGoogleModel(baseURL, urlSuffix), nil
case "aliyun":
return NewAliyunModel(baseURL, urlSuffix), nil
case "volcengine":
return NewVolcEngine(baseURL, urlSuffix), nil
case "vllm":
return NewVllmModel(baseURL, urlSuffix), nil
case "xai":
return NewXAIModel(baseURL, urlSuffix), nil
case "lmstudio":
return NewLmStudioModel(baseURL, urlSuffix), nil
case "ollama":
return NewOllamaModel(baseURL, urlSuffix), nil
case "openai":
return NewOpenAIModel(baseURL, urlSuffix), nil
case "groq":
return NewGroqModel(baseURL, urlSuffix), nil
case "azure-openai":
return NewAzureOpenAIModel(baseURL, urlSuffix), nil
case "nvidia":
return NewNvidiaModel(baseURL, urlSuffix), nil
case "openrouter":
return NewOpenRouterModel(baseURL, urlSuffix), nil
case "huggingface":
return NewHuggingFaceModel(baseURL, urlSuffix), nil
case "baidu":
return NewBaiduModel(baseURL, urlSuffix), nil
case "cohere":
return NewCoHereModel(baseURL, urlSuffix), nil
case "cometapi":
return NewCometAPIModel(baseURL, urlSuffix), nil
case "fishaudio":
return NewFishAudioModel(baseURL, urlSuffix), nil
case "mistral":
return NewMistralModel(baseURL, urlSuffix), nil
case "upstage":
return NewUpstageModel(baseURL, urlSuffix), nil
case "stepfun":
return NewStepFunModel(baseURL, urlSuffix), nil
case "baichuan":
return NewBaichuanModel(baseURL, urlSuffix), nil
case "jina":
return NewJinaModel(baseURL, urlSuffix), nil
case "localai":
return NewLocalAIModel(baseURL, urlSuffix), nil
case "xinference":
return NewXinferenceModel(baseURL, urlSuffix), nil
case "astraflow":
return NewAstraflowModel(baseURL, urlSuffix), nil
case "modelscope":
return NewModelScopeModel(baseURL, urlSuffix), nil
case "longcat":
return NewLongCatModel(baseURL, urlSuffix), nil
case "hunyuan":
return NewHunyuanModel(baseURL, urlSuffix), nil
case "tokenpony":
return NewTokenPonyModel(baseURL, urlSuffix), nil
case "tokenhub":
return NewTokenHubModel(baseURL, urlSuffix), nil
case "novita":
return NewNovitaModel(baseURL, urlSuffix), nil
case "avian":
return NewAvianModel(baseURL, urlSuffix), nil
case "replicate":
return NewReplicateModel(baseURL, urlSuffix), nil
case "togetherai":
return NewTogetherAIModel(baseURL, urlSuffix), nil
case "ppio":
return NewPPIOModel(baseURL, urlSuffix), nil
case "voyage":
return NewVoyageModel(baseURL, urlSuffix), nil
case "paddleocr":
return NewPaddleOCRModel(baseURL, urlSuffix), nil
case "xunfei":
return NewXunFeiModel(baseURL, urlSuffix), nil
case "deepinfra":
return NewDeepInfraModel(baseURL, urlSuffix), nil
case "mineru":
return NewMinerUModel(baseURL, urlSuffix), nil
case "jiekouai":
return NewJieKouAIModel(baseURL, urlSuffix), nil
case "302.ai":
return NewAI302Model(baseURL, urlSuffix), nil
case "mineru_local":
return NewMinerLocalUModel(baseURL, urlSuffix), nil
case "futurmix":
return NewFuturMixModel(baseURL, urlSuffix), nil
case "perplexity":
return NewPerplexityModel(baseURL, urlSuffix), nil
case "gpustack":
return NewGPUStackModel(baseURL, urlSuffix), nil
case "n1n":
return NewN1NModel(baseURL, urlSuffix), nil
case "bedrock":
return NewBedrockModel(baseURL, urlSuffix), nil
case "paddleocr_local":
return NewPaddleOCRLocalModel(baseURL, urlSuffix), nil
case "huaweicloud":
return NewHuaweiCloudModel(baseURL, urlSuffix), nil
default:
return NewDummyModel(baseURL, urlSuffix), nil
}
}