Files
ragflow/internal/entity/models/factory.go

76 lines
2.4 KiB
Go
Raw Normal View History

//
// 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 "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
Go: implement provider: xAI (#14550) Closes #14552 ### What problem does this PR solve? Add a Go driver for xAI (Grok models). The config file conf/models/xai.json has been in the repo since the early Go provider work, but internal/entity/models/factory.go had no case for "xai". So any xAI request fell through to the dummy driver and never reached the API. This PR adds the missing driver and wires it up. ### What this PR includes - New file internal/entity/models/xai.go with an XAIModel that implements the ModelDriver interface. - factory.go: route the "xai" provider name to NewXAIModel. ### How the driver works - xAI exposes an OpenAI-compatible API at https://api.x.ai/v1. - ChatWithMessages and ChatStreamlyWithSender post to /chat/completions in the same shape the moonshot and deepseek drivers use. - ListModels and CheckConnection call /models to confirm the API key works and to list available model ids. - reasoning_content is passed through for grok-3-mini and other xAI reasoning models, both in the non-stream and stream paths. - Encode, Rerank, and Balance are not part of the public xAI API at the moment, so they return a clear "not implemented" or "no such method" error. ### Type of change - [x] New Feature (non-breaking change which adds functionality) ### How was this tested? - go build ./internal/entity/models/... in a clean go 1.25 image (the go.mod minimum) returns exit 0 with no errors. - Method set of XAIModel matches the ModelDriver interface: NewInstance, Name, ChatWithMessages, ChatStreamlyWithSender, Encode, Rerank, ListModels, Balance, CheckConnection. - Pattern parity with the merged moonshot (#14433), volcengine (#14460), minimax (#14478), and vllm (#14532) PRs. --------- Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-06 06:16:37 +02:00
case "xai":
return NewXAIModel(baseURL, urlSuffix), nil
case "lmstudio":
return NewLmStudioModel(baseURL, urlSuffix), nil
Go: implement Encode (embeddings) in Ollama driver (#14664) ### What problem does this PR solve? The Ollama Go driver shipped with a stub \`Encode\` method that returned \`no such method\`, even though Ollama is one of the most common local LLM runners and exposes an OpenAI-compatible embeddings endpoint at \`/v1/embeddings\`. Ollama users routinely run local embedding models such as \`nomic-embed-text\`, \`mxbai-embed-large\`, or \`bge-m3\`. Pulled with \`ollama pull <model>\` and served on the same \`/v1\` namespace as chat. The existing \`ListModels\` already discovers them, but because \`Encode\` was a stub, a tenant who picked one of these models in the Go layer could not actually run an embedding call. ### What this PR includes - \`conf/models/ollama.json\`: add \`\"embedding\": \"embeddings\"\` under \`url_suffix\` so the driver can build the URL from config. - \`internal/entity/models/ollama.go\`: replace the \`Encode\` stub with a real implementation. Adds a small local response type that matches the OpenAI-compatible shape. No factory change. No interface change. ### How the driver works - Validate the model name. The API key is optional for local Ollama, so the Authorization header is only set when both \`apiConfig\` and \`ApiKey\` are non-nil and non-empty, the same pattern the recently merged CheckConnection PR (#14614) uses. - Resolve the region with a default fallback. Return a clear "missing base URL" error when the user has not configured the local access address yet. - Use a per-call \`context.WithTimeout(30s)\` and \`http.NewRequestWithContext\`, the same pattern the merged Aliyun Encode (#14647) uses. - Send \`{model, input: [texts]}\` in one request. - Parse \`data[*].embedding\` and copy each slice into a \`[][]float64\` indexed by \`data[*].index\`, so the output order matches the input order. - Handle both \`float64\` and \`float32\` element types. - Empty input returns \`[][]float64{}\` with no HTTP call. - Length mismatch between input and result, out-of-range index, and any missing slot all return clear errors instead of silent zero vectors. ### Type of change - [x] New Feature (non-breaking change which adds functionality) ### How was this tested? - \`go build ./internal/entity/models/...\` in a clean go 1.25 image returns exit 0. - The full method set on \`OllamaModel\` still matches the \`ModelDriver\` interface. - Pattern parity with the merged Aliyun Encode (#14647) and the existing SiliconFlow Encode. Closes #14662
2026-05-11 06:50:15 +02:00
case "ollama":
return NewOllamaModel(baseURL, urlSuffix), nil
Go: implement Encode (embeddings) in OpenAI driver (#14630) ### What problem does this PR solve? The OpenAI Go driver landed in #14605 with chat, list models, and check connection. Encode was left as a stub that returns \`not implemented\`. \`conf/models/openai.json\` already lists three embedding models out of the box: - text-embedding-ada-002 - text-embedding-3-small - text-embedding-3-large So a tenant who picked one of these in the Go layer could not actually run an embedding call. This PR fills the gap. ### What this PR includes - \`conf/models/openai.json\`: add \`\"embedding\": \"embeddings\"\` under \`url_suffix\` so the driver can build the URL from config. This matches the \`URLSuffix.Embedding\` field used by other drivers (siliconflow, zhipu-ai). - \`internal/entity/models/openai.go\`: replace the Encode stub with a real implementation that POSTs to \`/v1/embeddings\`. Adds a small local response type \`openaiEmbeddingResponse\`. No factory change. No interface change. ### How the implementation works - Validate \`apiConfig\` and the API key, validate the model name. Use the existing \`baseURLForRegion\` helper so an unknown region fails fast with a clear error. - Wrap the request with \`context.WithTimeout(nonStreamCallTimeout)\` so the call has a clear deadline. Same pattern as \`ChatWithMessages\` and \`ListModels\` already use in this file. - Send all input texts in one request. The OpenAI API accepts the \`input\` field as an array. - Parse \`data[*].embedding\` and copy each slice into a \`[][]float64\` indexed by \`data[*].index\` so the output order matches the input order even if the API returns items in a different order. - Handle both \`float64\` and \`float32\` element types, the way the SiliconFlow driver does. - An empty input slice returns \`[][]float64{}\` with no HTTP call. - Non-200 responses propagate the upstream status line and body. - A final pass checks that every input slot got a vector. If any slot is still nil, return a clear error so the caller does not silently use a zero vector. ### Type of change - [x] New Feature (non-breaking change which adds functionality) ### How was this tested? - \`go build ./internal/entity/models/...\` in a clean go 1.25 image (the go.mod minimum) returns exit 0. - The full method set on \`OpenAIModel\` still matches the \`ModelDriver\` interface. - Pattern parity with the existing SiliconFlow Encode implementation (\`internal/entity/models/siliconflow.go\`). Closes #14629 --------- Co-authored-by: Jin Hai <haijin.chn@gmail.com>
2026-05-10 04:31:37 +02:00
case "openai":
return NewOpenAIModel(baseURL, urlSuffix), nil
case "nvidia":
return NewNvidiaModel(baseURL, urlSuffix), nil
case "openrouter":
return NewOpenRouterModel(baseURL, urlSuffix), nil
case "huggingface":
return NewHuggingFaceModel(baseURL, urlSuffix), nil
Go: implement provider: Baidu (#14741) ### What problem does this PR solve? This PR completes the Baidu Qianfan provider integration in RAGFlow. **The following functionalities are now supported:** - [x] Chat / Think Chat / Stream Chat / Stream Think Chat - [x] Embedding - [x] Rerank - [x] Model listing - [x] Provider connection checking - [ ] Balance ----- **Verified examples from the CLI:** ```plaintext RAGFlow(user)> embed text 'what is rag' 'who are you' with 'embedding-3@test@zhipu-ai' dimension 16; +-----------+-------+ | dimension | index | +-----------+-------+ | 16 | 0 | | 16 | 1 | +-----------+-------+ RAGFlow(user)> rerank query 'what is rag' document 'rag is retrieval augment generation' 'rag need llm' 'famous rag project includes ragflow' with 'qwen3-reranker-4b@test@baidu' top 2; +-------+---------------------+ | index | relevance_score | +-------+---------------------+ | 0 | 0.974821150302887 | | 1 | 0.14223189651966095 | | 2 | 0.08632347732782364 | +-------+---------------------+ RAGFlow(user)> think chat with 'deepseek-v3.2@test@baidu' message 'who r u' Thinking: Hmm, the user is asking for a simple introduction. This is straightforward – no need for overcomplication. I should give a clear, friendly response that covers my basic identity as an AI assistant, my purpose, and my capabilities. Keeping it concise but informative is key here. Mentioning my creator Anthropic adds credibility, and ending with an offer to help invites further interaction. No need for technical details unless the user asks later. Answer: Hello! I'm an AI assistant created by Anthropic, designed to help with a wide variety of tasks. You can think of me as a helpful digital companion—I can answer questions, assist with writing, help solve problems, provide explanations, and engage in conversation on many topics. I'm here to help with whatever you need! How can I assist you today? Time: 8.103902 RAGFlow(user)> stream think chat with 'deepseek-v3.2@test@baidu' message 'who r u' Thinking: mm, the user is asking "who r u" with casual spelling. This is a straightforward identity question. should give a clear, friendly introduction without overcomplicating it. Can start with my core function as an AI assistant, mention my creator, and briefly state my key capabilities. response should be welcoming and invite further interaction since this seems like an introductory question. Keeping it concise but covering the essentials: who I am, what I do, and how I can help. Answer: ! I am DeepSeek, an AI assistant created by DeepSeek Company. I'm designed to help answer questions, provide information, assist with various tasks, and engage in conversations on a wide range of topics. I'm here to assist you with whatever you need - whether it's answering questions, helping with analysis, writing, coding, or just having a friendly chat!Is there anything specific I can help you with today? 😊 Time: 7.219703 RAGFlow(user)> list supported models from 'baidu' 'test' +--------------------------------------+ | model_name | +--------------------------------------+ | ernie-3.5-8k-preview | | ernie-4.0-8k | | ernie-4.0-turbo-8k-latest | | ernie-4.0-turbo-8k-preview | | ernie-4.0-8k-preview | | ernie-speed-pro-128k | | ernie-char-fiction-8k | | ernie-3.5-8k | | ernie-3.5-128k | | ernie-lite-pro-128k | | ernie-novel-8k | | ernie-4.0-turbo-8k | | ernie-4.0-turbo-128k | | ernie-4.0-8k-latest | | irag-1.0 | | ........... | | glm-5.1 | | ernie-image-turbo | | deepseek-v4-pro | | deepseek-v4-flash | | ernie-5.1 | +--------------------------------------+ RAGFlow(user)> check instance 'test' from 'baidu' SUCCESS ``` Additionally, this PR fixes an incorrect error message typo: Before: ```go fmt.Errorf("API requestssss failed with status %d: %s : %s", ...) ``` After: ```go fmt.Errorf("API request failed with status %d: %s", ...) ``` This PR mainly improves provider compatibility, API completeness, and runtime stability. ### Type of change * [x] Bug Fix (non-breaking change which fixes an issue) * [x] New Feature (non-breaking change which adds functionality) * [x] Refactoring
2026-05-09 19:21:13 +08:00
case "baidu":
return NewBaiduModel(baseURL, urlSuffix), nil
default:
return NewDummyModel(baseURL, urlSuffix), nil
}
}